In C++, a destructor is a special member function that is automatically called when an object goes out of scope or is explicitly deleted. It is responsible for cleaning up any resources allocated by the object during its lifetime. However, when dealing with inheritance and polymorphism, a regular destructor may not be sufficient to properly deallocate resources in derived classes. This is where virtual destructors come into play.
Why do we need Virtual Destructors?
Consider a scenario where you have a base class with a pointer to a derived class. When you delete an object through a base class pointer, the destructor of the derived class is not called if the base class destructor is not virtual. This can lead to resource leaks and undefined behavior.
By declaring a destructor as virtual, you ensure that the destructor of the most derived class is called when deleting an object through a base class pointer. This allows for proper cleanup of resources in both the base class and derived classes.
Example:
Let’s illustrate the concept of virtual destructors with an example:
#include <iostream>
class Base {
public:
Base() {
std::cout << "Base constructor called" << std::endl;
}
virtual ~Base() {
std::cout << "Base destructor called" << std::endl;
}
};
class Derived : public Base {
public:
Derived() {
std::cout << "Derived constructor called" << std::endl;
}
~Derived() {
std::cout << "Derived destructor called" << std::endl;
}
};
int main() {
Base* obj = new Derived();
delete obj;
return 0;
}
In this example, we have a base class called “Base” and a derived class called “Derived”. Both classes have their respective constructors and destructors.
In the main function, we create a pointer of type “Base” and assign it the address of a dynamically allocated “Derived” object. This is an example of polymorphism, where we can treat a derived object as a base object.
When we delete the object through the base class pointer, the virtual destructor ensures that the destructor of the most derived class, “Derived”, is called first. This is evident from the output:
Base constructor called
Derived constructor called
Derived destructor called
Base destructor called
As you can see, the destructors are called in the reverse order of their constructors. The virtual destructor in the base class allows the derived class destructor to be called, ensuring proper cleanup of resources.
Conclusion
Virtual destructors are essential when dealing with inheritance and polymorphism in C++. They ensure that the destructor of the most derived class is called when deleting an object through a base class pointer. This allows for proper cleanup of resources in both the base class and derived classes, preventing resource leaks and undefined behavior.
Remember to always declare the destructor of a base class as virtual if you intend to use polymorphism and dynamically allocate objects. This simple practice can save you from potential bugs and memory leaks in your code.