Virtual Base Class in C++

C++ is a language that is widely praised because of its flexibility and power when used for object-oriented programming. Another of such less obvious characteristics of C++ is the virtual base class. This concept is about issues that occur in some kinds of inheritance taxonomic structures.

So, in this blog, we shall explain what virtual base classes are, their significance, and a case study that explains why virtual base classes are useful.

Understanding Virtual Base Classes

The term virtual base class in C++ is used to overcome the Diamond Problem in Multiple Inheritance. This issue arises because a derived class is developed from two classes that are themselves evolved from a single mother class. It can cause uncertainty to determine which of the versions of the base class the derived class has to use or inherit.

A virtual base class makes certain that only a single edition of the base class exists in the derived classes hierarchy, hence the elimination of ambiguity.

The Diamond Problem Explained

Here’s an example of the diamond problem:

#include <iostream>

class A {
public:
    void display() {
        std::cout << "Base class A" << std::endl;
    }
};

class B : public A {}; // Class B inherits from A
class C : public A {}; // Class C inherits from A
class D : public B, public C {}; // Class D inherits from B and C

When you create an object of class D and try to call a method from A, the compiler will face ambiguity:

D obj;
obj.display(); // Error: Ambiguous access to 'display'

At a given time, both B and C are included in the compilations and the compiler is not sure which A to compile.

Solution: Virtual Base Classes

When you make a declaration for A as a virtual base class, what you are effectively doing is to guarantee that there will be only one instance of A in the hierarchy.

#include <iostream>

class A {
public:
    void display() {
        std::cout << "Base class A" << std::endl;
    }
};

class B : virtual public A {}; // Class B inherits from A as a virtual base class
class C : virtual public A {}; // Class C inherits from A as a virtual base class
class D : public B, public C {}; // Class D inherits from both B and C

Now, when D inherits from both B and C, it shares the single instance of A:

D obj;
obj.display(); 
Output: 
Base class A

Real-Life Use Case of Virtual Base Classes

Now let’s consider an example of using and modeling relationships among different classes in a University system to clarify the using of virtual base classes in object-oriented programming.

Problem Setup: University Hierarchy

  1. Problem Setup: University Hierarchy
  2. Base Class: Person (features: name of the person, age of the person).
  3. Intermediate Classes: Faculty (inherits from Person; attribute: department), Student (inherits from Person; attribute: course)
  4. Derived Class: TeachingAssistant (an amalgamation of two classes Faculty and Student).

In case we do not have the virtual base classes, a TeachingAssistant will serve as the duplicate of the Person class, and since it doesn’t share it, it will have the name and the age attributes twice, which is confusing.

Code Without Virtual Base Classes

#include <iostream>
#include <string>

using namespace std;

class Person {
public:
    string name;
    int age;
};

class Faculty : public Person {
public:
    string department;
};

class Student : public Person {
public:
    string course;
};

class TeachingAssistant : public Faculty, public Student {};

int main() {
    TeachingAssistant ta;
    ta.name = "Alice"; // Ambiguity: which 'name' to use?
    return 0;
}

This code will fail due to ambiguity when accessing name or age.

Code With Virtual Base Classes

By declaring Person as a virtual base class, you solve the problem:

#include <iostream>
#include <string>

using namespace std;

class Person {
public:
    string name;
    int age;
};

class Faculty : virtual public Person {
public:
    string department;
};

class Student : virtual public Person {
public:
    string course;
};

class TeachingAssistant : public Faculty, public Student {};

int main() {
    TeachingAssistant ta;
    ta.name = "Alice";            // No ambiguity
    ta.age = 25;
    ta.department = "Computer Science";
    ta.course = "Data Structures";

    cout << "Name: " << ta.name << endl;
    cout << "Age: " << ta.age << endl;
    cout << "Department: " << ta.department << endl;
    cout << "Course: " << ta.course << endl;

    return 0;
}

Output

Name: Alice
Age: 25
Department: Computer Science
Course: Data Structures

This approach ensures that the TeachingAssistant has only one instance of Person, avoiding ambiguity and redundancy.

Key Benefits of Virtual Base Classes

  1. Avoids Redundant Copies: Creates a guarantee for the fact that there is only one base class in the hierarchy at all.
  2. Eliminates Ambiguity: It decides when conflicts between accesses of members of the base class occur.
  3. Efficient Memory Usage: Minimises the number of instance copies hence saving memory space.

Conclusion

Using virtual base classes in C++ also provides nice solutions to the so-called diamond problem and gives a clean way of designing Inheritance diagrams. Even though they may look multifaceted they turned out to be extremely helpful when dealing with real-life situations, for example with our university hierarchy example above they are a necessity for C++ developers. So when to use it and how to do so can go a long way towards making better object-oriented designs in C++.