Search code examples
c++virtual-inheritancediamond-problem

Diamond problem with only 1 virtual inheritance


Does this still solve the diamond problem?

class A
{};

class B : virtual A
{};

class C : A
{};

class D : B, C
{};

Edit: If not, what is it then? Is it the same as this?

class A
{};

class B : A
{};

class C : A
{};

class D : B, C
{};

Or is it something even else?


Solution

  • Diamond problem and ambiguous call to common base members can be best described through the following pictorial equivalent which also give an insight of the memory model

    Example 1

    class A
    {void foo(){};};
    
    class B :public A
    {};
    
    class C :public  A
    {};
    
    class D :public  B,public  C
    {};
    

    Since Inheritance simply puts the implementation of two objects one after another, all methods of Base class A gets duplicated in derived class B and C, which has an equivalent pictorial representation as

                              A              A
                              |              |
                              |              |
                               B             C
                                 \         /
                                    \    /
                                      D
    

    Example 2

    class A
    {};
    
    class B :public  virtual A
    {};
    
    class C :public  A
    {};
    
    class D :public  B,public  C
    {};
    

    With the virtual keyword, compiler generates a vtable for Derived class B with a vptr (virtual pointer) in the vtable of B which stores an Offset of the Base class A. For C, it still copies all method of base class A. So class D, via Base class B refers the members of base class A via a vptr where are Class C refers the members of base class A as a duplicate copy. So the diamond problem and ambiguity still persist.

                                   A         A
                                 /           |
                               /             |
                               B             C
                                 \         /
                                    \    /
                                      D
    

    Example 3

    class A
    {};
    
    class B :public  virtual A
    {};
    
    class C :public  virtual A
    {};
    
    class D :public  B,public  C
    {};
    

    Now when both the derived classes B and C inherits A virtually, Compiler creates a Vtable for both B and C and creates a vptr in each of its vtable to refer the offset of the Base Class A. This finally solves the Diamond Problem as there is only one copy visible via B or C

                                      A                                          
                                   /     \
                                 /         \                                
                               B             C
                                 \         /
                                    \    /
                                      D