tags:

views:

101

answers:

2

Playing around with MSVC++ 2005, I noticed that if the same class is defined several times, the program still happily links, even at the highest warning level. I find it surprising, how comes this is not an error?

module_a.cpp:

#include <iostream>
struct Foo {
  const char * Bar() { return "MODULE_A"; }
};
void TestA() { std::cout << "TestA: " << Foo().Bar() << std::endl; }

module_b.cpp:

#include <iostream>
struct Foo {
  const char * Bar() { return "MODULE_B"; }
};
void TestB() { std::cout << "TestB: " << Foo().Bar() << std::endl; }

main.cpp:

void TestA();
void TestB();
int main() {
  TestA();
  TestB();
}

And the output is:

TestA: MODULE_A
TestB: MODULE_A
+3  A: 

It is an error - the code breaks the C++ One Definition Rule. If you do that, the standard says you get undefined behaviour.

The code links, because if you had:

struct Foo {
  const char * Bar() { return "MODULE_B"; }
};

in both modules there would NOT be a ODR violation - after all, this is basically what #including a header does. The violation comes because your definitions are different ( the other one contains the string "MODULE_A") but there is no way for the linker (which just looks at class/function names) to detect this.

anon
A: 

The compiler might consider that the object is useless besides its use in Test#() function and hence inlines the whole thing. That way, the linker would never see that either class even existed ! Just an idea, though.

Or somehow, linking between TestA and class Foo[#] would be done inside compilation. There would be a conflict if linker was looking for class Foo (multiple definition), but the linker simply does not look for it !

Do you have linking errors if compiling in debug mode with no optimizations enabled ?

Benoît
It is not inlining. If it were the outputs would be correct. The compiler is probably discarding one (randomly selected) symbol. As Neil pointed, if they both were the same that would be perfectly ok.
David Rodríguez - dribeas