Summary: In this tutorial, we will learn what the diamond problem is, when it happens and how we can solve it using virtual inheritance in C++.

What is the Diamond Problem?

When we inherit more than one base class in the same derived class and all these base classes also inherit another but same single class (super parent), multiple references of the super parent class become available to the derived class.

So, it becomes unclear to the derived class, which version of the super parent class it should refer to.

Consider the following program for instance:

#include <iostream>
using namespace std;

//super parent class
class A{
public:
    void name(){
         cout << "This is class A \n";
    }
};

//base class I
class B: public A{};

//base class II 
class C: public A{};
 
//derived class
class D: public B, public C{};
 
int main()
{
    D d;
    d.name();
 
    return 0;
}

There is no syntactical error in the above program but still, if we try to compile then it returns the following compilation error:

line 24|error: request for member ‘name’ is ambiguous

This is because two instances of class A’s name() method is available for class D, one through class B, and the other through class C.

Diamond Problem in C++

In this case, the compiler gets confused and cannot decide which name() method it should refer to.

This ambiguity often occurs in the case of multiple inheritances and is popularly known as the diamond problem in C++.

To remove this ambiguity, we use virtual inheritance to inherit the super parent.

What is Virtual Inheritance?

Virtual inheritance in C++ is a type of inheritance that ensures that only one copy or instance of the base class’s members is inherited by the grandchild derived class.

It is implemented by prefixing the virtual keyword in the inheritance statement.

Example:

class A: virtual public B{
    //members
}

If we now apply virtual inheritance in our previous example, only one instance of class A would be inherited by class D (i.e. B::A and C::A will be treated as the same).

#include <iostream>
using namespace std;

//super parent class
class A{
public:
    void name(){
         cout << "This is class A \n";
    }
};

//base class I
class B: virtual public A{};

//base class II 
class C: virtual public A{};
 
//derived class
class D: public B, public C{};
 
int main()
{
    D d;
    d.name();
 
    return 0;
}

Output:

Virtual Inheritance in C++

Now because there is only one reference of class A’s instance is available to the child classes, we get the proper diamond-shaped inheritance.

Also, If we need to override any of the super parent class’s method (class A) in the child classes, we should override it till the very derived class, like the following. Otherwise, the compiler will throw no unique overrider error.

#include <iostream>
using namespace std;

//super parent class
class A{
public:
    virtual void name(){
         cout << "This is class A \n";
    }
};

//base class I
class B: virtual public A{
public:
    void name(){
         cout << "This is class B \n";
    }
};

//base class II 
class C: virtual public A{
public:
    void name(){
         cout << "This is class C \n";
    }
};
 
//derived class
class D: public B, public C{
public:
    void name(){
         cout << "This is class D \n";
    }
};
 
int main()
{
    D d;
    d.name();
 
    return 0;
}

In this tutorial, we understood the concept of virtual inheritance and were able to solve the diamond problem using the same in C++.

Leave a Reply