c++linkerconflict

How these names conflict is resolved in C++?


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?


Solution

  • 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.