Why doesn't this code work? (C ++ OOP) public inherits
I would like some help to explain this phenomenon:
#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 does not? Thanks in advance!
Note: I am well aware of virtual inheritance, I just want to know what is the difference between Row27 and Row28 - why throw a compile error when the other is not?
source to share
Because you are using non-virtual inheritance for inference A
, that indirectly creates two sub-type objects A
in each type object D
. The compiler is unable to resolve which sub-sequential object you are referencing when performing a pointer-to-output conversion to a pointer-to-base conversion and throws an error.
To have only one type sub-object A
generated for type objects D
, you must make inheritance A
virtual by inheritance paths that D
infer fromA
class B1: virtual public A
{
// ...
};
class B2: virtual public A, public B1
{
};
EDIT:
I tried to compile your example in Visual Studio 2010 SP1 which gives me a warning about the definition B2
:
class B2: public A, public B1
{
};
1>sotest.cpp(18): warning C4584: 'B2' : base-class 'A' is already a base-class of 'B1'
1> sotest.cpp(6) : see declaration of 'A'
1> sotest.cpp(11) : see declaration of 'B1'
In other words, for some reason VC10 seems to consider inheritance from A
redundant and ignore it. That's why compilation A* a = &b;
: class B2
inherits from A
only once (through B1
). The same does not apply to D
, because VC10 probably does not have redundant inheritance to ignore, but D
effectively inherits from A
twice (through B1
and through B2
).
I ignore the reasons why VC10 behaves this way, and I don't know if there is a compiler option to suppress this behavior. Notably, both GCC 4.7.2 and Clang 3.2 refuse to compile assignments A* a = &b;
.
source to share
For future users, this looks like:
I just tried this on GCC 4.7.1 and Clang 3.2 and I get a compiler error if I don't use virtual inheritance. which compiler are you using? - Andy Prowl
VS2010 does compile, but throws a warning that suggests it ignores B2 inheritance from A. This is why Row 27 works. I think this is a strange behavior of VS2010 and I don't know if there is any way to disable it (other than looking at all warnings as errors) - Andy Prowl
Thank you @ Andy Prowl.
source to share