I would like some help explaining this phenomenom:
#include <iostream>
using namespace std;
class A
{
public:
void m() {cout<<"A::m "<<this<<endl;};
};
class B1: public A
{
public:
void m() {cout<<"B::m "<<this<<endl;};
};
class B2: public A ,public B1
{
};
class D : public B2
{};
int main()
{
B2 b;
D d;
A* a = &b; // Row 27
//error: a = &d; Base class 'A' is ambiguous // Row 28
return 0;
}
Why does the code in Row27 work but the code in Row28 doesnt?
Thank in advance!
Note: I am well aware of virtual inheritance, I just want to know what is the difference between Row27 and Row28 – why one throw a compilation error when the other not?
Because you are using non-virtual inheritance to derive from
A, which indirectly creates two sub-objects of typeAin every object of typeD. The compiler cannot disambiguate which sub-object you refer to when doing the pointer-to-derived to pointer-to-base conversion, and issues an error.In order to have only one sub-object of type
Agenerated for objects of typeD, you have to make inheritance fromAvirtual along the inheritance paths which makeDderive fromA:EDIT:
I tried to compile your example on Visual Studio 2010 SP1, which gives me a warning about the definition of
B2:In other words, for some reason VC10 seems to consider the inheritance from
Aredundant and ignores it. This is why the assignmentA* a = &b;compiles:class B2actually inherits fromAonly once (throughB1). The same is not true ofD, because VC10 has probably no redundant inheritance to ignore, andDeffectively inherits fromAtwice (throughB1and throughB2).I ignore the reasons why VC10 behaves this way, and I do not know if there is a compiler option to suppress this behavior. Remarkably, both GCC 4.7.2 and Clang 3.2 refuse to compile the assignment
A* a = &b;.