In this tutorial, we will learn about the C++ destructor, virtual as well as pure virtual destructors. From this tutorial, you will also get a clear idea about when the destructors are called, and also about their rules and regulations in detail.
A member function that deletes an object is referred to as a destructor. The compiler will automatically invoke a destructor whenever an object leaves its scope. Destructors are unique member functions that behave in the exact opposite way to constructors; whereas constructors initialize an object, destructors destroy (or delete) the object.
A destructor is the inverse of constructors and is defined similarly to a constructor. The destructors mainly destroy the class objects. In a class, it can only be defined once, and it must share the same name as the class. It is automatically invoked, just like constructors. But a tilde sign (~) is added just before it.
When an object of a class is destroyed, destructors are typically used to deallocate memory and do other cleanings for the object and the members of the class. When a class object exits its scope or is purposefully eliminated, then the destructor is called.
~className{
// Some code
};
Example 1
class X {
public:
// Constructor for class X
X();
// Destructor for class X
~X();
};
Example 2
#include<iostream>
using namespace std;
class Test
{
public:
Test()
{
cout<<"\n Constructor executed";
}
~Test()
{
cout<<"\n Destructor executed";
}
};
main()
{
Test t;
return 0;
}
Output:
Constructor executed Destructor executed
When an object leaves its scope, a destructor function is automatically invoked:
The destructors in C++ are mainly called in the following situations:
As they don't accept any arguments and return nothing, destructors differ from the normal member functions. Destructor names are preceded by a tilde (~), and they share the same name as their class.
When an item is removed from the scope or deleted, the following series of events occur to complete its destruction:
Undefined behavior arises when a derived class object with a non-virtual destructor is deleted using a pointer of the base class type. This issue can be resolved by adding a virtual destructor to the base class definition.
The Base class's destructors can be virtual. Every time an upcast is performed, the base class's destructors must be turned virtual to ensure that the object is properly destroyed when the program terminates.
The static cast operation is used to print a void pointer's contents. It changes the pointer's void* type to the appropriate data type for the address the pointer is storing:
#include <iostream>
using namespace std;
// declare a class
class base {
public:
// Destructor
~base() {
cout << "The Destructor base." << endl;
}
};
class derived : publicbase {
public:
// Destructor
~derived() {
cout << "The Destructor derived." << endl;
}
}
int main() {
base* b = new derived; // Upcasting
delete b;
return 0;
}
Output:
The Destructor base
Explanation
The delete b
command in the above example will only call the destructor of the Base class, which is undesirable since it prevents the object of the Derived class from being destroyed because its destructor is not ever called. It causes a memory leak.
#include <iostream>
using namespace std;
// declare a class
class base {
public:
virtual ~base() {
cout << "The Destructor base." << endl;
}
};
class derived : publicbase {
public:
~derived() {
cout << "The Destructor derived." << endl;
}
}
int main() {
base* b = new derived; // Upcasting
delete b;
return 0;
}
Output:
The Destructor base The Destructor derived
Explanation: When we have a Virtual destructor inside the base class, the desired behavior is that the Derived class's destructor is called first, followed by the Base class's destructor.
When a destructor's starting value is set to 0. It is referred to as a virtual destructor and is stated in the base class. A pure virtual destructor is another option, similar to a virtual destructor. However, it must be declared in the base class.
The primary difference between a Virtual and a Pure Virtual Destructor is that a Pure Virtual Destructor will make its Base class Abstract, which means that you will be unable to construct objects of that class.
It's not necessary for the derived classes to include pure virtual destructors.