假设我有以下代码:
foo.h
class Foo
{
// ...
};
foo.cpp
#include "foo.h"
// Functions for class Foo defined here...
假设 Foo
内置于静态库 foo.lib
中。
现在假设我有以下内容:
foo2.h
class Foo
{
// ...
};
foo2.cpp
#include "foo2.h"
// Functions for class Foo defined here...
这被内置到一个单独的静态库 foo2.lib
中。
现在,如果我将 foo.lib
和 foo2.lib
重新链接到一个可执行程序 foo.exe
中,它应该会报错吗class Foo
被定义了两次?
根据我的经验,编译器或链接器都没有提示。
我不希望编译器提示,因为它们是在单独的翻译单元中定义的。
但是为什么链接器不报错呢?
链接器如何区分 Foo
类的两个版本?它通过装饰符号来工作吗?
最佳答案
您可以在多个翻译单元中对一种类类型进行多个定义,但要遵守一些相当严格的限制,这意味着这些定义必须几乎相同。 (3.2 [basic.def.odr])
这也适用于枚举类型、具有外部链接的内联函数、类模板、非静态函数模板、类模板的静态数据成员、类模板的成员函数或某些模板参数不适用的模板特化指定。
这实际上意味着您可以遵循将类定义放在头文件中并在多个翻译单元中使用它的常见做法,只要包含序列中没有任何会导致 token 序列的差异或类定义中使用的任何名称的含义在多个翻译单元之间有所不同。
你不能在整个程序中定义多个类的非内联成员函数。
违反这些规则中的任何一条都会导致未定义的行为,因此不需要编译序列的任何部分来生成诊断或导致任何特定的行为,因此如果您有一个类的两个定义略有不同,我似乎可以工作或可能在运行时引起奇怪的问题。
如果您有两个具有相同名称和相同签名的类的非内联成员函数定义,您很可能会在链接时出错,但这不是语言保证。
值得注意的是,如果相同实体的两个定义位于库(相同或不同的库)的不同目标文件中,则您的程序可能实际上不会包含给定实体的多个定义。链接器的传统工作方式是迭代选择有助于解析程序中符号的目标文件,但它们会遗漏无助于解析符号的目标文件。这意味着在包含第一个具有定义的目标文件后,无需包含具有替代定义的第二个目标文件。
关于c++ - 具有相同名称的类 - 是否仅限于同一翻译单元?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2816285/