根据单一定义规则,类和结构定义不得在单个翻译单元中重复。
但是,如果它们实际上是定义,那么为什么允许它们在多个翻译单元中重复出现。为什么在那种情况下链接器不抛出多重定义错误?
例如- 下面应该按照相同的逻辑抛出多重定义错误
测试.h
#ifndef TEST
#define TEST
class s {
int a;
int b;
};
#endif
测试1.cpp
#include "test.h"
int main() {}
测试2.cpp
#include "test.h"
But then why is the case that they are allowed to be repeated in multiple translation units, if they are in reality definitions.
在语言层面,答案很简单:因为标准是这么说的,特别是在 [basic.def.odr]/6 中。
There can be more than one definition of a class type, enumeration type, inline function with external linkage ([dcl.inline]), inline variable with external linkage ([dcl.inline]), class template, non-static function template, static data member of a class template, member function of a class template, or template specialization for which some template parameters are not specified ([temp.spec], [temp.class.spec]) in a program provided that each definition appears in a different translation unit, and provided the definitions satisfy the following requirements. […]
当然,语言规则之所以如此,是有原因的。在实现层面,类的定义只是告诉编译器,对相应类类型的对象进行操作的代码必须如何处理业务,例如,对象成员位于何处等。但是类定义本身并不会真正生成代码。编译器有必要在使用该类的每个翻译单元中查看每个类类型的定义,以便它可以独立地为每个翻译单元生成正确的代码。类类型的定义在每个翻译单元中也必须相同,以便为每个翻译单元生成的代码与为所有其他翻译单元生成的代码兼容。
Why doesnt the linker throw a multiple definition error in that case ?
在符号级别工作的链接器最终只能看到生成的目标代码。并且类定义在机器代码级别没有明确的表示。类的概念在那个级别上并不真正存在。它们存在于代码运行的方式中,而不是直接存在于代码中。如果你愿意,他们可以生活在装配线之间……