c ++包含不同的头文件,在多个源文件中具有相同的类实现

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了c ++包含不同的头文件,在多个源文件中具有相同的类实现相关的知识,希望对你有一定的参考价值。

例如

class Dummy {
public:
  Dummy() { std::cout << "a.h" << std::endl; }
};

b.h

class Dummy {
public:
  Dummy() { std::cout << "b.h" << std::endl; }
};

从.曹操

#include "a.h"

void test() {
  Dummy a;
}

的.曹操

#include "b.h"

int main() {
  Dummy a;
  return 0;
}

然后使用命令编译源文件

g++ d.cc c.cc

输出是

b.h

但是有了命令

g++ c.cc d.cc

输出是

a.h

我的问题是为什么没有multiple definition错误以及为什么输出取决于编译的顺序?

答案

您的程序有未定义的行为。总结一下C ++标准,我的重点是[basic.def.odr/6]

在程序中可以有多个类类型的定义,[...]只要每个定义出现在不同的翻译单元中,并且定义满足以下要求即可。鉴于这样一个名为D的实体在多个翻译单元中定义,那么

  • D的每个定义应由相同的令牌序列组成;和
  • [...]

[...]如果D的定义满足所有这些要求,则行为就好像存在D的单个定义。如果D的定义不满足这些要求,那么行为是不确定的。

所以你观察到两种不同的行为。完全可以接受,因为语言对你应该看到的行为没有任何限制。你违反了合同,所以没有保证。

现在,从实际的角度来看,你看到的只是GCC在上述合同下运作。它假定你不会违反它(即使你这样做),并且忽略了对Dummy和/或其成员的任何后续重新定义。第一个“胜出”。

另一答案

编译器不检测多重定义错误,因为c.ccd.cc是单独的翻译单元。它们彼此分开处理;每个都有一个Dummy::Dummy构造函数的定义。

链接器不会检测到多重定义错误,因为标头中的Dummy::Dummy构造函数的定义被视为内联定义。该语言允许每个翻译单元中的内联定义,只要它们全部相同即可。通常,这些定义相同的原因是它们都来自相同的头文件,但是标准要求定义相同,即使它们来自不同的文件。

当您的程序违反此规则时,其行为未定义。这就是为什么你的程序表现不同,这取决于在翻译过程中改变翻译单元顺序的看似无关的行为。

以上是关于c ++包含不同的头文件,在多个源文件中具有相同的类实现的主要内容,如果未能解决你的问题,请参考以下文章

合并具有不同列名但定义相同的多个CSV

如何在一个 EmbeddedDatabaseBuilder 中组合多个具有不同分隔符的 SQL 文件?

WINDOWS操作系统下的C语言头文件存放在哪个目录中?

如何让g ++搜索特定目录中的头文件?

如何让g ++搜索特定目录中的头文件?

C 头文件