2

我有以下 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

  1. 为什么只有名称相同 但主体不同时没有编译器/链接器错误?
  2. 为什么单一的定义C::foo(..)既适用于 static静态版本又适用于非静态版本?
  3. 或者,如果这只是编译器的另一个未定义行为案例,我们可以阻止它吗?
4

1 回答 1

1

您的程序违反了一个定义规则并且具有未定义的行为。从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),除了如果对象在 D 的所有定义中具有相同的文字类型,并且该对象用常量表达式(5.19)初始化,并且值使用对象的(但不是地址),并且该对象在 D 的所有定义中具有相同的值;和

[ ...省略了与示例不直接相关的内容... ]

如果 D 的定义满足所有这些要求,那么程序的行为就好像有一个 D 的定义。如果 D 的定义不满足这些要求,那么行为是未定义的

您不会收到编译器错误,因为它一次只能“看到”一个翻译单元。链接器及其错误消息超出了 C++ 标准的范围,所以我相信无法给出一个正确的答案,为什么它不能诊断。我想它只需要C遇到的第一个符号并丢弃其余符号。

于 2013-07-14T14:09:28.413 回答