Search code examples
c++language-lawyervirtual-inheritancediamond-problem

Why is single virtual inheritance not enough to resolve the dreaded diamond problem?


struct B { int i; };
struct D1 : virtual B {};
struct D2 : B {};  // <-- not virtual
struct DD : D1, D2 {};

Having coded above, still the compiler demands D2 also to be virtual:

DD d;
d.i = 0; // error: request for member `i' is ambiguous

What I don't understand is, once you have prompted compiler that B is virtual with respect to DD (via D1) then why it still i is ambiguous ?

(If my memory serves correct, the older VC++ (in 2006), was capable enough to make out this just with single virtual inheritance)


Solution

  • B is not virtual with respect to DD - it is virtual with respect to D1. At the time D2 is created, it contains a full copy of B. So now DD has two implementations of B: one as part of D2, and one at the end (pointed by D1). And having two copies of i, using it is indeed ambiguous.

    Had D2 also used virtual inheritance, instead of containing a copy of B, it would have contained a pointer to the instance of B that D1 is also pointing at, and DD would have contained only one instance of B.

    I'll try to illustrate the memory layouts, hope this comes out right...:

    Your case, with one virtual inheritance and one non-virtual -

    |    D1    |   D2 + B |    B    |
    +--+-------+----------+---------+
     |   vptr to B           ^
     +-----------------------|
    

    Having both D1 and D2 inherit virtually -

    |   D1   |   D2   |   B   |
    +--+-----+---+----+-------+
     |         |         ^
     +---------+---------|