質問

I have 2 files as below, which declare a same name 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;
}

It compiles fine with g++ C1.cpp C2.cpp!

  1. Why is there no compiler/linker error when only the names are same but the bodies are not?
  2. Why the single definition of C::foo(..) serves for both the static and non-static versions?
  3. Or if this is just another undefined behavior case from compiler, can we prevent it?
役に立ちましたか?

解決

Your program violates One definition rule and has undefined behaviour. From n3337 3.2/5, emphasis mine:

There can be more than one definition of a class type (Clause 9), enumeration type (7.2), inline function with external linkage (7.1.2), class template (Clause 14), non-static function template (14.5.6), static data member of a class template (14.5.1.3), member function of a class template (14.5.1.1), or template specialization for which some template parameters are not specified (14.7, 14.5.5) in a program provided that each definition appears in a different translation unit, and provided the definitions satisfy the following requirements. Given such an entity named D defined in more than one translation unit, then

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

in each definition of D, corresponding names, looked up according to 3.4, shall refer to an entity defined within the definition of D, or shall refer to the same entity, after overload resolution (13.3) and after matching of partial template specialization (14.8.3), except that a name can refer to a const object with internal or no linkage if the object has the same literal type in all definitions of D, and the object is initialized with a constant expression (5.19), and the value (but not the address) of the object is used, and the object has the same value in all definitions of D; and

[... omitted stuff that's not directly related to the example ...]

If the definitions of D satisfy all these requirements, then the program shall behave as if there were a single definition of D. If the definitions of D do not satisfy these requirements, then the behavior is undefined.

You can't get a compiler error because it only "sees" one translation unit at a time. The linker and it's error messages are out of the scope of C++ standard, so I believe there can't be a de iure answer why it doesn't diagnose. I guess it just takes the first C symbol that encounters and discards the rest.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top