Inheritance is a key feature of object-oriented programming that involves acquiring or inheriting all of the attributes and behaviors of one class and then extending or specializing them.
Inheritance can be seen everywhere in the world. For example, a newborn child inherits attributes (hair, color, etc.) from their father and mother. But after acquiring attributes from their parents, they also develop their own personalities on top of those attributes.
Consider the example of a car.
Both electric and gasoline cars inherit the properties of a car.
Now, there is a special case if there is another class – a Hybrid
class, for example – that inherits both the Electric
and Gasoline
class. We can see in the diagram that it will form a diamond.
The hybrid car is both an electric car and a gasoline car. These kinds of special cases will result in a diamond problem.
This diamond creates a problem, because now the Hybrid
class has two copies of the Car
class for each path.
Let’s look at the following code snippet.
#include <iostream>using namespace std;class Car{public:Car(){cout << "Car Constructor" <<endl;}};class Electric : public Car{public:Electric(){cout << "Electric Constructor" <<endl;}};class Gasoline : public Car{public:Gasoline(){cout << "Gasoline Constructor" <<endl;}};class Hybrid : public Electric , public Gasoline{public:Hybrid(){cout << "Hybrid Constructor" <<endl;}};int main() {Hybrid h;return 0;}
If you make a Hybrid
class object in the main, you see that the Car Constructor
is called two times. This is because of the diamond problem. The Hybrid
class object has two copies of the Car
class for each of its parents, respectively.
This might not appear to be a big issue. For larger programs, however, in which the grandparent also contains tens of classes above it, the overhead of this duplication is tremendous.
So, how can this problem be solved?
The above problem can be solved by writing the keyword virtual
. When we use virtual
keyword, it is called virtual inheritance. When we use virtual inheritance, we are guaranteed to get only a single instance of the common base class. In other words, the hybrid class will have only a single instance of the car class, shared by both the Electric and Gasoline classes. By having a single instance of car, we’ve resolved the problem. We will make both the Electric
and Gasoline
classes into virtual base classes.
#include <iostream>using namespace std;class Car{public:Car(){cout << "Car Constructor" <<endl;}};class Electric : virtual public Car{public:Electric(){cout << "Electric Constructor" <<endl;}};class Gasoline : virtual public Car{public:Gasoline(){cout << "Gasoline Constructor" <<endl;}};class Hybrid : public Electric , public Gasoline{public:Hybrid(){cout << "Hybrid Constructor" <<endl;}};int main() {Hybrid h;return 0;}
After updating the code, we can see that the hybrid object only contains one Car
class copy.