A virtual destructor is a destructor declared within the base class with the virtual keyword. When deleting a derived class object using a pointer to a base class, the base class should be defined with a virtual destructor.
Virtual destructors help prevent the problem of memory leaks and undefined behavior. If a virtual destructor is not used, then only the base class destructor is called, and the resources of derived class is not cleaned up.
The Syntax for declaring a virtual destructor is given below −
classBase{public:virtual~Base(){// base class destructor}};
Example
The following example demonstrates how to use a virtual destructor. The virtual destructor calls the destructor of both classes i.e. base and child class −
#include <iostream>usingnamespace std;classBase{public:Base(){
cout <<"Base Constructor\n";}virtual~Base(){
cout <<"Base Destructor\n";}};classDerived:public Base{public:Derived(){
cout <<"Derived Constructor\n";}~Derived(){
cout <<"Derived Destructor\n";}};intmain(){
Base *basePtr =newDerived();delete basePtr;return0;}
The output of the above code is given below −
Base Constructor Derived Constructor Derived Destructor Base Destructor
Why We Need Virtual Destructors?
Given below are the reasons why virtual destructors are needed −
- When you do not use a virtual base class destructor while deleting a derived class object, it results in undefined behavior.
- Virtual destructors make sure to delete the object of derived class too while deleting the base class object.
- It avoids memory leak.
- Virtual destructors maintain the order of execution of destructors i.e., first derived class, then base class.
Example: Non-Virtual Destructor
In the following example, the virtual destructor is not used. In the output, it can be observed that only the base class destructor has been called and the destructor of derived class is skipped.
#include <iostream>usingnamespace std;classBase{public:// Non-virtual destructor~Base(){
cout <<"Base class destructor called.\n";}};classDerived:public Base{public:~Derived(){
cout <<"Derived class destructor also called.\n";}};intmain(){
Base* ptr =newDerived();// Only Base destructor will be calleddelete ptr;return0;}
The output of the above code is given below −
Base class destructor called.
Example: Virtual Destructor
In this example, we have used a virtual destructor on base class Base. In the output, it can be observed that the destructor of both base and derived class is called and it maintains the reverse order of deletion.
#include <iostream>usingnamespace std;classBase{public:// Virtual destructorvirtual~Base(){
cout <<"Base class destructor called.\n";}};classDerived:public Base{public:~Derived(){
cout <<"Derived class destructor also called.\n";}};intmain(){
Base* ptr =newDerived();// Both Base class and derived class destructor will be calleddelete ptr;return0;}
The output of the above code is given below −
Derived class destructor also called. Base class destructor called.
When to Use Virtual Destructors?
You can use a virtual destructor in the following scenarios.
- If a virtual function is used, then use virtual destructor. Since, virtual functions are used in polymorphism to override base class. Using a virtual destructor can free up memory of both, base and derived class.
- In inheritance, make the destructor of base class a virtual destructor as the destructor of derived class is skipped and only the base class destructor is called, it may cause a memory leak.
- If abstract base or pure virtual function is used, then use virtual destructor on base class.
Virtual Destructor Table (Vtable)
In C++, virtual table(vtable) is a lookup table which is used by the compiler to implement virtual functions or virtual destructors. For each class that has at least one virtual function or virtual destructor, the compiler will create a vtable for that class.
A vtable has pointers to all virtual functions and the virtual destructor of a class. In a class, each object has a hidden pointer known as vptr or virtual pointer. This vptr points to the vtable of the class, which is then used to call the respective destructor. Here is a diagram representation of the vtable for the given code −

Example
In this example, we have implemented the above code snippet to override the virtual functions of class A in class B and class C.
#include <iostream>usingnamespace std;classA{public:virtualvoidf1(){
cout <<"A::f1 called"<< endl;}virtualvoidf2(){
cout <<"A::f2 called"<< endl;}virtual~A(){
cout <<"Class A destructor called"<< endl;}};classB:public A{public:voidf1()override{
cout <<"B::f1 called"<< endl;}voidf2()override{
cout <<"B::f2 called"<< endl;}~B()override{
cout <<"Class B destructor called"<< endl;}};classC:public A{public:voidf1()override{
cout <<"C::f1 called"<< endl;}voidf2()override{
cout <<"C::f2 called"<< endl;}~C()override{
cout <<"Class C destructor called"<< endl;}};intmain(){
A* ptrB =newB();
A* ptrC =newC();
cout <<"Calling functions using pointer B:"<< endl;
ptrB->f1();
ptrB->f2();
cout <<"Calling functions using pointer C:"<< endl;
ptrC->f1();
ptrC->f2();// Calling B's destructor then A's destructordelete ptrB;// Calling C's destructor then A's destructordelete ptrC;return0;}
The output of the above code is given below −
Calling functions using pointer B: B::f1 called B::f2 called Calling functions using pointer C: C::f1 called C::f2 called Class B destructor called Class A destructor called Class C destructor called Class A destructor called
Conclusion
The virtual destructor is used when working with inheritance and polymorphism. Its main purpose is to make sure that the destructors of derived classes are also called when an object is deleted through a base class pointer. This prevents memory leaks and undefined behavior.
Leave a Reply