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 : p开发者_StackOverflow中文版ublic 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.
I'm guessing you aren't actually linking your conflictlib. But really, just don't do that. If you absolutely MUST, use namespaces.
The answer is very simple. You have lied to compiler, and in return the compiler is serving your lie back to you. Internal implementation of functions is such that they are just lined up in some function table for each class. When you have different class declaration the compiler deduces the function table according to it, but the deduction is wrong. In this table there are no function names, so compiler can't detect the fault condition.
You have two different definitions of class A. This is a violation of ODR. The program therefore is not a valid C++ program. Compilers are not required to diagnose this error.
精彩评论