Virtual Destructor in C++ with Examples

Virtual Destructor in C++ with Examples

You should know the following before gaining information about virtual destructor.

1. What is a destructor and why should you use it?
2. What is new and delete?

Let us understand more about the above points.

Destructor is an instance member function of a class. Its name is same as the name of class but preceded by tilde (~) symbol. It should be defined to release the resources allocated to an object.

Read more about new and delete in details here: New & Delete in C++

Base or Parent class pointer can point to the object of any of its descendant class (or derived class) but its converse is not true.

For Example:-
#include<iostream.h>
using namespace std;

//Parent Class
class Integer
{
private:
 int num;

public:
 void setData(int n1)
 {
  num = n1;
 }
};

//Derived or Child class of Integer
class PositiveInteger: public Integer
{
private:
 int num2;

public:
 void setData(int n2)
 {
  num2 = n2;
 }
};

int main() 
{  
 //Pointer of Parent class Integer
 Integer *I;    
 
 //declaring Object of Child class
 PositiveInteger P;
 
 //base class pointer pointing to child class object.
 I = &P;
 return 0;  
}
Here, I is a pointer of base class Integer (I is a base class pointer) and P is an object of derived class PositiveInteger. Since I is a base class pointer, it can point to the derived class object like P in this case.

Now take a look at another example.
#include<iostream>
using namespace std;

//Parent Class
class Integer
{
private:
 int num1;

public:
 void setValue1(int n1)
 {
  num1 = n1;
 }
 
 void showValue1()
 {
  cout << "Value1: " << num1 << endl;
 }
};

//Derived or Child class of Integer
class PositiveInteger: public Integer
{
private:
 int num2;

public:
 void setValue2(int n2)
 {
  num2 = n2;
 }
 
 void showValue2()
 {
  cout << "Value2: " << num2 << endl;
 }
};

int main()
{
 Integer *I = new PositiveInteger;
 
 I->setValue1(12);    //correct
 I->setValue2(15);    //error
 I->showValue1();     //correct
 I->showValue2();     //error
 
 return 0;  
}
It will throw error in line I->setValue2(15); and I->showValue2(); because early binding is done here. 

The compiler will try to map the function call with its correct definition. It then see the type of I (because early binding is done here) and I is of Integer type. So, the compiler will go to class Integer and search for setValue2() and showValue2() functions.

There is no functions named setValue2() and showValue2() exists inside Integer class and that is why it will throw an error in line I->setValue2()15; and I->showValue2();

Points To Remember:

If pointer of parent class points to the object of child class then:
1. the pointer can only invoke those members which are declared in the parent class.
2. the pointer can't invoke the members which are not declared in parent class (i.e. it can't invoke child class members).


Virtual Destructor in C++

1. Destructor is a member function of a class.
2. Destructor preceded by virtual keyword is called virtual destructor.
2. It is used to free up the memory that is occupied in the program by derived class object in case of dynamic memory allocation (DMA).
3. It ensures that both derived and base classes' destructors are called properly.
4. It called derived class destructor first and then the base class destructor.


Why to use Virtual Destructor?

Virtual destructor is used to avoid memory leaks issue in the program. 

To understand it properly, Consider the following program carefully.
#include<iostream>
using namespace std;
class baseClass
{
 int num1;
 
public:
 void Function1()
 {
  cout << "I am Function1 of baseClass" << endl;
 }
 
 ~baseClass()
 {
  cout << "I am Destructor of baseClass" << endl;
 }
};
 
 class derivedClass : public baseClass
 {
  int num2;
  
 public:
  void Function2()
  {
   cout << "I am Function2 of derivedClass" << endl;
  }
  
  ~derivedClass()
  {
   cout << "I am Destructor of derivedClass" << endl;
  }
 };
 
int main()
{
 baseClass *B1 = new derivedClass;
 
 // B1 -> Function2();   (error)
  
 B1 -> Function1();   //correct
 delete B1;           //only baseClass destructor will call.
 return 0;
}



/* OUTPUT

I am Function1 of baseClass
I am Destructor of baseClass

*/
Here, pointer object of baseClass B1 pointing to derived class when deleted only the parent class destructor is called due to the early binding done by the compiler.

Child class destructor will never be called here which leads to memory leaks issue in case of DMA. To solve this problem, you must use virtual destructor.


For Example: virtual destructor in C++
#include<iostream>
using namespace std;
class baseClass
{
 int num1;
 
public:
 void Function1()
 {
  cout << "I am Function1 of baseClass" << endl;
 }
 
 virtual ~baseClass()
 {
  cout << "I am Destructor of baseClass" << endl;
 }
};
 
 class derivedClass : public baseClass
 {
  int num2;
  
 public:
  void Function2()
  {
   cout << "I am Function2 of derivedClass" << endl;
  }
  
  ~derivedClass()
  {
   cout << "I am Destructor of derivedClass" << endl;
  }
 };
 
int main()
{
 baseClass *B1 = new derivedClass;
 
 // B1 -> Function2();   (error)
  
 B1 -> Function1();   //correct
 delete B1;           //only baseClass destructor will call.
 return 0;
}
Output:
I am Function1 of baseClass
I am Destructor of derivedClass
I am Destructor of baseClass
Here, late binding is done by the compiler due to virtual keyword.

The compiler will now consider the content that base class pointer (B1) is pointing to (B1 is pointing to derivedClass). So, the compiler will go to derivedClass to invoke destructor of derivedClass and then it goes to baseClass for invoking destructor of baseClass.

There is no need of writing virtual before the destructor of derived class. The compiler will understand that the derived class destructor is also a virtual destructor due to the virtual keyword written during the declaration of base class destructor.


<< Previous                                                                                      Next >>
Previous
Next Post »