在不同源文件中声明的同名类没有编译器/链接器错误
Posted
技术标签:
【中文标题】在不同源文件中声明的同名类没有编译器/链接器错误【英文标题】:No compiler/linker error for same name classes declared in different source files 【发布时间】:2013-07-14 13:07:48 【问题描述】:我有如下 2 个文件,它们声明了同名 class C
:
// C1.cpp
class C
public: void foo (int, float);
;
int main ()
C c;
c.foo(1, 2.3);
void C::foo (int, float)
// C2.cpp
class C
public:
int i; // <--- extra variable
void foo (int, float); // <--- non static
;
void foo ()
C c;
c.foo(0, 0.0);
c.i = 0;
它与g++ C1.cpp C2.cpp
编译得很好!
-
为什么只有名称相同时没有编译器/链接器错误
但尸体不是?
为什么
C::foo(..)
的单一定义同时适用于
static
和非静态版本?
或者如果这只是编译器的另一个未定义行为案例,
我们可以预防吗?
【问题讨论】:
我认为这是“UB,不需要诊断”。 @downvoter,这个问题还不足以被否决。 您需要标准报价吗?它基本上说“一个类可以有多个定义,但它们都需要由相同的标记序列组成”和“定义中的所有名称都需要引用相同的实体”。正如 Kerred 所说,1)和 2)的答案是 UB,不需要诊断。 3) 的答案是,我猜,就是不要这样做。 @jrok,我不知道应该是什么答案。如果您觉得有什么可以帮助的,请发布它。这将对我和未来的访客有所帮助。我在 SO 中找不到类似的问题。对 (3) 的回答不能是“不要这样做”,当您有多个人参与庞大的代码库时,在最坏的情况下它必须是“不可能”。 【参考方案1】:您的程序违反了One definition rule 并且具有未定义的行为。来自n3337 3.2/5
,强调我的:
类类型可以有多个定义(第 9 条)、枚举类型 (7.2)、内联函数 外部链接(7.1.2),类模板(第 14 条),非静态函数模板(14.5.6),静态数据成员 类模板 (14.5.1.3) 的成员函数、类模板的成员函数 (14.5.1.1) 或模板特化 某些模板参数在程序中未指定(14.7、14.5.5)只要每个定义 出现在不同的翻译单元中,并且定义满足以下要求。给定 这样一个名为 D 的实体定义在多个翻译单元中,那么
—D 的每个定义都应由相同的标记序列组成; 和
——在D的每个定义中,对应的名字,根据 至 3.4,应指在 D 的定义中定义的实体,或 在重载决议(13.3)和 在匹配部分模板特化(14.8.3)之后,除了 一个名称可以引用一个具有内部链接或没有链接的 const 对象,如果 该对象在 D 的所有定义中都具有相同的字面量类型,并且 对象用常量表达式(5.19)初始化,值 对象的(但不是地址)被使用,并且对象具有 D 的所有定义中的值相同;和
[...省略了与示例不直接相关的内容...]
如果 D 的定义满足所有这些要求, 那么程序的行为就好像有一个 D 的定义。如果 D 的定义不满足 这些要求,则行为未定义。
您不会收到编译器错误,因为它一次只能“看到”一个翻译单元。链接器及其错误消息超出了 C++ 标准的范围,所以我相信无法de iure 回答为什么它不能诊断。我猜它只需要遇到并丢弃其余符号的第一个 C
符号。
【讨论】:
以上是关于在不同源文件中声明的同名类没有编译器/链接器错误的主要内容,如果未能解决你的问题,请参考以下文章