0

As I have understood, a class can be defined in multiple translation units aslong they're identical. With that in mind, consider the following examples:

 //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;
}

This compiles and I don't get a crash.

If I do the following changes:

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

I get a crash. Why does one result in a crash and the other doesn't. Also, am I not violating ODR in the first example? If I am, why does it compile ok?

4

2 回答 2

1

The program is ill-formed for the reason you stated. The compiler is not required a diagnostics, but I don't see a point in discussing reasons for a crash in an ill-formed program.

Still, let's do it:

The first example probably doesn't crash because FooBar's behavior doesn't affect the run of main. The method is called, it does something, and that's it.

In the second example, you attempt to return a Foo. FooBar returns the version of Foo defined in 2.cpp. main appears in 1.cpp so it expects the version of Foo defined in 1.cpp, which is a completely different version - different members, sizes. You most likely get a corruption on the destructor. (just a guess)

EDIT: this does break the one definition rule:

3.2 One definition rule [basic.def.odr]

6) There can be more than one definition of a class type [...] in a program provided that each definition appears in a different translation unit, and provided the definitions satisfy the following requirements. [...]

  • each definition of D shall consist of the same sequence of tokens;

[...]

于 2012-10-12T23:51:24.667 回答
0

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

  1. 编译器翻译具有提供的标头的 cpp 文件。它生成一个 .obj 文件。在您的情况下, o.bj 文件将引用 data-struct Foo。并且不会有任何其他细节。

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

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

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

于 2012-10-13T00:12:16.183 回答