Virtual base class in C++

Virtual base class in C++

What is Virtual Base Class in C++?

  • Virtual base classes in C++ are essential for resolving ambiguity and eliminating redundant copies of common base class members in complex class hierarchies.
  • In C++, when you have a class that is inherited by multiple derived classes, you might encounter a problem known as the "diamond problem".
  • This happens when a class inherits from two or more classes that have a common base class.
  • To solve this issue, C++ introduced the concept of a virtual base class.
1   A
2  / \
3 B   C
4  \ /
5   D
  • Here, both B and C inherit from A, and D inherits from both B and C.
  • If you try to access a member of A through D, the compiler might get confused about which instance of A to use.

Virtual base class in C++ syntax

  • The virtual keyword is used before the inheritance declaration of the base class Base.
  • Both Derived1 and Derived2 inherit virtually from Base.
1class Base {
2public:
3    // Base class members and methods
4};
5
6class Derived1 : virtual public Base {
7public:
8    // Derived1 class members and methods
9};
10
11class Derived2 : virtual public Base {
12public:
13    // Derived2 class members and methods
14};
15
16
17class MostDerived : public Derived1, public Derived2 {
18public:
19    // MostDerived class members and methods
20};

C++ Virtual base class Example

C++ code example illustrating the use of virtual base classes to avoid ambiguity in a diamond-shaped class hierarchy:
1#include <iostream>
2using namespace std;
3
4class Animal {
5public:
6    Animal(string name) : name(name) {}
7
8    void eat() {
9        cout << name << " is eating." << endl;
10    }
11
12private:
13    string name;
14};
15
16class Mammal : virtual public Animal {
17public:
18    Mammal(string name) : Animal(name) {}
19
20    void run() {
21        cout << name << " is running." << endl;
22    }
23};
24
25class Bird : virtual public Animal {
26public:
27    Bird(string name) : Animal(name) {}
28
29    void fly() {
30        cout << name << " is flying." << endl;
31    }
32};
33
34class Bat : public Mammal, public Bird {
35public:
36    Bat(string name) : Animal(name), Mammal(name), Bird(name) {}
37};
38
39int main() {
40    Bat bat("Batty");
41
42    bat.eat(); // Accessing Animal's method
43    bat.run(); // Accessing Mammal's method
44    bat.fly(); // Accessing Bird's method
45
46  
47    return 0;
48}
  • Both Mammal and Bird inherit virtually from Animal.
  • Class Bat inherits from both Mammal and Bird.
When we create a Bat object:
  • We avoid the diamond problem by using virtual inheritance for Mammal and Bird.
  • This ensures there's only one instance of the Animal base class.

Why Virtual Base Class is Important?

  • Virtual inheritance specifies that the base class is inherited only once, which resolves any ambiguity in member access.
  • Without virtual inheritance, if you have a member in a common base class, each derived class will have its own copy. This can lead to ambiguity and problems.

Constructor and Destructor in Derived Classes

  • When you have a class hierarchy, constructors and destructors are called in a specific order.
  • The base class constructor is called before the derived class constructor, and destructors are called in the reverse order.
1#include <iostream>
2using namespace std;
3
4class A {
5public:
6    A() {
7        cout << "Constructing A\n";
8    }
9    ~A() {
10        cout << "Destructing A\n";
11    }
12};
13
14class B : virtual public A { // Virtual inheritance
15public:
16    B() {
17        cout << "Constructing B\n";
18    }
19    ~B() {
20        cout << "Destructing B\n";
21    }
22};
23
24class C : virtual public A {
25public:
26    C() {
27        cout << "Constructing C\n";
28    }
29    ~C() {
30        cout << "Destructing C\n";
31    }
32};
33
34class D : public B, public C {
35public:
36    D() {
37        cout << "Constructing D\n";
38    }
39    ~D() {
40        cout << "Destructing D\n";
41    }
42};
43
44
45int main() {
46    D d;
47    return 0;
48}
  • Both B and C inherit virtually from A. This is indicated by the virtual keyword in the inheritance declaration.
  • In the main function, we create an object of class D. This triggers the constructors and destructors.
Output:
1Constructing A
2Constructing B
3Constructing C
4Constructing D
5Destructing D
6Destructing C
7Destructing B
8Destructing A
  • This output demonstrates the order of constructor and destructor calls in a class hierarchy with virtual base classes.
  • The destructors are called in the reverse order of constructors.

Conclusion

Virtual base classes in C++ are essential for resolving ambiguity and eliminating redundant copies of common base class members in complex class hierarchies. They ensure a single instance of the base class, maintain object consistency, and enhance code clarity and maintainability, particularly in multiple inheritance scenarios.