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.