Say I have this physical structure:
/
+-- conflicttest
| +-- A.cpp
| +-- A.h
| +-- main.cpp
+-- libconflict
| +-- conflict
| | +-- A.h
| | +-- B.h
| +-- A.cpp
| +-- B.cpp
These are the sources of libconflict, take a deep breath:
class B
header in libconflict:
// libconflict B.h
class B
{
public:
void bar();
protected:
int j_;
};
class B
implementation in libconflict:
// libconflict B.cpp
#include "conflict/B.h"
void B::bar()
{
std::cout << "B::bar" << std::endl;
}
class A
header in libconflict:
// libconflict A.h
# include "conflict/B.h"
class A : public B
{
public:
A();
private:
int i_;
};
class A
implementation in libconflict:
#include "conflict/A.h"
A::A()
{
std::cout << "libconflict A is alive" << std::endl;
i_ = 51; // some random fields and values... I should admit I am lost
j_ = 47;
}
Now the sources of conflicttest, it's almost over:
class A
header in conflicttest:
// conflicttest A.h
class A
{
public:
A();
void foo();
};
class A
implementation in conflicttest:
// conflicttest A.cpp
#include "A.h"
A::A()
{
std::cout << "A is alive" << std::endl;
}
void A::foo()
{
std::cout << "A::foo" << std::endl;
}
and finally, main.cpp
:
// main.cpp in conflicttest
#include "conflict/A.h"
int main()
{
B* b = new A;
b->bar();
return 0;
}
Phew... I am using Visual Studio 2010 to build this solution. conflicttest
is an executable which is linked against the static library libconflict
.
This compiles like a charm, but, believe it or not, the output is :
A is alive
B::bar
The linker actually uses the symbol A
from conflicttest
which is absolutely not a B
and worse, it can invoke B::bar()
.
I am lost, how come the compiler doesn't complain?
You have violated the One Definition Rule.
The compiler didn't complain because it is limited in the things it can detect when crossing translation unit boundaries.