Consider the situation associated with a non-virtual base class:
class A { int a; } class B : public A { int b; } class C : public A { int c; } class D : public B, public C { int d; }
The memory location is possible here:
+-------------+ | A: int a; | +-------------+ | B: int b; | +-------------+ | A: int a; | +-------------+ | C: int c; | +-------------+ | D: int d; | +-------------+
D ends with two subobjects of A , because it inherits from B and C , and both of them have subobject A
Pointers to member variables are usually implemented as an integer offset from the beginning of the object. In this case, the integer offset for int a in object A is zero. Thus, a "pointer to int a type A " may simply be an integer zero offset.
To convert a "pointer to an int a type A " to a "pointer to an int a type B ", you just need an integer offset in the subobject A located in B (the first subobject A ).
To convert a "pointer to an int a type A " to a "pointer to an int a type C ", you just need an integer offset in subobject A located in C (second subobject A ).
Since the compiler knows where B and C refers to A , the compiler has enough information on how to downcast from A to B or C
Now consider the situation with a virtual base class:
struct A { int a; } struct B : virtual public A { int b; } struct C : virtual public A { int c; } struct D : public B, public C { int d; }
Possible memory layout:
+-------------+ | B: ptr to A | ---+ | int b; | | +-------------+ | | C: ptr to A | ---+ | int c; | | +-------------+ | | D: int d; | | +-------------+ | | A: int a; | <--+ +-------------+
Virtual base classes are usually implemented using B and C (which are actually derived from A ) contain a pointer to one subobject A Pointers to subobject A are required because the location of A relative to B and C not constant.
If all that we had was a "pointer to int a type A " we will not be able to attribute it to a "pointer to int a type B " since the locations of subjects B and C can change relative to A A does not have back pointers to B and C , so we just don't have enough information for downcast to work.