c++ - 为什么 ld 链接器允许使用相同方法定义多个类?

标签 c++ linker g++ ld

考虑这个文件,first.cpp,包含一个类定义和使用:

#include <iostream>

struct Foo
{
    Foo(){ std::cout << "Foo()" << std::endl; }
    ~Foo(){ std::cout << "~Foo()" << std::endl; }
};

int main(){
    Foo f;
    return 0;
}

另一个,second.cpp,包含一个冲突的类定义:

#include <iostream>

struct Foo
{
    Foo();
    ~Foo();
};

Foo::~Foo(){ std::cout << "wrong ~Foo()" << std::endl; }

当定义了两个具有相同名称的函数时,链接器会提示重复符号,但是这些具有重复类方法的文件编译时不会出错。

我用这些命令编译:

$ g++ -c second.cpp -o second
$ g++ second first.cpp -o first

对第二个 g++ 调用的参数重新排序不会改变输出。

first 运行时,输出如下:

$ ./first
Foo()
wrong ~Foo()

为什么链接器允许重复的类方法?如果显然允许,为什么会打印 wrong ~Foo()

最佳答案

再次,未定义的行为。您的程序对 Foo 的析构函数有多个定义,这意味着它违反了 ODR。程序是错误的,任何事情都可能发生。

为什么链接器不接收它?当一个函数在类定义中定义时,它是隐式的inline。编译器通常将这些函数标记为“弱符号”。然后链接器获取所有翻译单元并尝试解析符号。如果需要,链接器将删除弱符号(即,如果符号已在其他地方定义)。

从程序的实际输出来看,编译器似乎实际上并没有内联对构造函数的调用,因此在运行时将其分派(dispatch)给链接器留下的符号(非弱符号)


Why linker allows to have duplicate methods?

因为所有(但最多一个)都是弱符号(即 inline)

Why, in this case, wrong ~Foo() is printed?

因为调用没有内联,并且链接器丢弃了弱符号

关于c++ - 为什么 ld 链接器允许使用相同方法定义多个类?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10754350/

相关文章:

C++:SFINAE 区分填充和范围构造函数?

c++ - 简单的 if 循环无法正常工作

visual-studio-2010 - 静态链接,Visual Studio和FLANN

linux - 在 Linux 中使用 --image-base 确保程序加载低于 4 GB

c++ - 无法使用 openssl c++ 进行编译

c++ - 编译和链接 .so 后的运行时 "symbol lookup error"

c++ - 在 g++ 中转储类/结构成员变量

c++ - MIPS 模拟器 --- 将指令读入内存 (C++)

c++ - 指针初始化

linux - ELF格式的重定位信息在哪里?