为什么 ld 链接器允许具有相同方法的多个类定义
Why does the ld linker allow multiple class definitions with the same methods?
考虑这个文件,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
。编译器通常将这些函数标记为"弱符号"。然后,链接器获取所有翻译单元并尝试解析符号。如果需要,链接器将删除弱符号(即,如果符号已在其他地方定义)。
截至程序的实际输出,看起来编译器实际上并没有内联对构造函数的调用,因此在运行时调度到链接器留下的符号(非弱符号)
为什么链接器允许有重复的方法?
因为所有(但最多一个)都是弱符号(即 inline
)
为什么在这种情况下,打印了错误的 ~Foo()?
因为调用未内联,并且链接器删除了弱符号
相关文章:
- 在方法定义中显式指定命名空间
- 没有针对完全专用模板类的外联虚拟方法定义
- 将虚拟方法定义为私有方法时会发生什么情况?
- 单独的类声明和方法定义文件问题
- Eclipse CDT 不了解方法定义是什么
- C 方法定义具有模板
- Eclipse CDT将方法定义定义到标头文件
- 模板方法定义的问题 - 错误C2244:无法将函数定义与现有声明匹配
- 如何为 Product* getProductFromID(std::string)编写方法定义;.
- gdb 中的方法定义没有源代码
- 方法定义中的错误"passing const List<int> as this argument discards qualifiers"
- Sendmessage在方法定义内部无法正常工作
- C 公共方法定义后定义
- C++模板方法定义在类中不匹配
- 为什么通用模板方法定义与模板类专用化不匹配?
- 方法定义中的C++模板参数
- C++方法定义和变量声明
- 在继承层次结构中将方法定义为虚拟方法一次,以使多态性发挥作用
- 未为非访问器方法定义C++类属性
- 无法将一个类的方法定义为另一个类的好友