繁体   English   中英

在不同的翻译单元中定义的类

[英]Class defined in different translation units

据我了解,一个类可以在多个翻译单元中定义,只要它们是相同的即可。 考虑到这一点,请考虑以下示例:

 //1.cpp

class Foo{
 public:
  int i;
};


void FooBar();

void BarFoo(){
  Foo f;
}


int main(){
 FooBar();
 BarFoo();
}

//2.cpp

class Foo{
 public:
  std::string s;
};

void FooBar(){
  Foo f;
}

这样编译,我不会崩溃。

如果我进行以下更改:

//1.cpp
 Foo FooBar();
//2.cpp
 Foo FooBar(){
   Foo f;
   return f;
 }

我崩溃了 为什么一个会导致崩溃,而另一个却不会。 另外,在第一个示例中我是否没有违反ODR? 如果是的话,为什么编译正常?

由于您指出的原因,程序格式错误。 编译器不是必需的诊断程序,但是在讨论格式错误的程序中导致崩溃的原因时,我没有任何意义。

不过,让我们做吧:

第一个示例可能不会崩溃,因为FooBar的行为不会影响main的运行。 该方法被调用,它执行某些操作,仅此而已。

在第二个示例中,您尝试返回Foo FooBar返回2.cpp定义的Foo版本。 main1.cpp出现,因此它期望在1.cpp定义的Foo版本,这是完全不同的版本-不同的成员,大小。 您最有可能在析构函数上发生损坏。 (只是一个猜测)

编辑:这确实违反了一个定义规则:

3.2一个定义规则[basic.def.odr]

6)程序中的类类型可以有多个定义,只要每个定义出现在不同的翻译单元中,并且这些定义满足以下要求。 [...]

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

[...]

这是编译器/链接器的工作方式:

  1. 编译器转换具有提供的标头的cpp文件。 它生成一个.obj文件。 在您的情况下,o.bj文件将引用数据结构Foo 并且将没有任何其他细节。

  2. 链接器将.obj文件链接在一起。 它仅比较字符串名称。 在obj文件中,您具有相同的Foo 名称匹配。 对于链接器,这是同一件事。

  3. 之后,您开始程序。 它很可能会崩溃。 更具体地说,它将显示未定义的行为。 它可以进入无限循环,显示奇怪的消息等。

您有责任在cpp文件中为每个cpp文件的翻译提供相同的标题或定义。 现有的软件工具无法为您检查。 这就是它的工作方式。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM