【问题标题】:How does the c++ linker choose which definition of a class to link into an executablec++ 链接器如何选择将哪个类的定义链接到可执行文件中
【发布时间】:2015-11-16 19:44:31
【问题描述】:

我在头文件foo.h 中有一个类foo,它根据是否定义了宏而以不同的方式打印。

foo.h

#pragma once
#include <iostream>

class foo
{
public:
    void print()
    {
#ifdef GOOD
        std::cout << "good\n";
#else
        std::cout << "bad\n";
#endif
    }
};

然后我有两个 cpp 文件,good.cppbad.cpp,其中包括 foo.h - 一个定义宏,另一个不定义。

好.cpp

#define GOOD
#include "foo.h"

void good()
{
    foo f;
    f.print();
}

坏的.cpp

#include "foo.h"

void bad()
{
    foo f;
    f.print();
}

最后,在我的主程序中,我有了这个

main.cpp

extern void good();
extern void bad();

int main(int argc, char* argv[])
{
    good();
    bad();
}

使用 VC++ 2013,这将打印以下输出

bad
bad

为什么链接器选择了foo 的“坏”版本?有没有办法强制链接器选择特定版本的foo

【问题讨论】:

  • 1) 没有 C++ 链接器。 2) 不要为不相关的语言添加标签。
  • One Definition Rule "其他违规,尤其是跨越翻译单元的违规,不需要诊断。" ¯_(ツ)_/¯
  • 链接器有多种定义可供选择。它掷硬币并选择一个。然而,它的随机数生成器在密码学上并不安全。
  • @PeterHuene:第 3.2 节“一个定义规则”第 3 段明确排除了内联函数。由于在类声明中定义的成员函数是隐式内联的,print() 是一个内联函数。那么程序违反了规则的哪一部分
  • @matz 内联函数可以有多个定义(即在多个翻译单元中有一个定义,因为它是内联的),但定义必须相同。这违反了该规则。

标签: c++ visual-studio-2013 linker


【解决方案1】:

如果在多个翻译单元中定义了具有外部链接的类,则所有定义必须相同。通过在具有不同GOOD 值的不同翻译单元中包含两次foo.h,您生成了foo 类的两个不同定义。这是格式错误的,不需要诊断,任何事情都可能发生。

您问的关于选择“哪个”类定义的问题没有意义,因为类在翻译生成的目标文件中并不“物理地”存在。相反,每个包含类定义的翻译单元都是在类确实在每个翻译单元中都有该定义的假设下编译的。当翻译单元链接在一起时,如果这个假设被证明是不正确的,那么可能会发生一些不好的事情。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-06
    • 2018-04-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多