Why write a Virtual Destructor but not a Virtual Constructor?
Updated: May 26
"Of course base class destructors should be virtual if you're going to delete polymorphically (i.e., delete via a pointer to base)!" - Herb Sutter
In this blog, I will discuss a very basic concept related to destructor. It is a basic concept but important. In any Early or Mid-level C++ interview, you can expect a question from this.
So the structure of the blog is as below
You can create any object in many ways. You can create a static object, non-static object, dynamically allocate memory for an object.
When you create an object in any way, there is a function get called Constructor. This constructor takes care of memory allocation for the object and initialization of member data.
A constructor performs its work in this order (Ref):
It calls base class and member constructors in the order of declaration.
If the class is derived from virtual base classes, it initializes the object's virtual base pointers.
If the class has or inherits virtual functions, it initializes the object's virtual function pointers. Virtual function pointers point to the class's virtual function table to enable the correct binding of virtual function calls to code.
It executes any code in its function body.
When your created object goes out of scope or dies for any reason, It calls a special function called Destructor. This function takes care of all kinds of cleanup. Your object may be holding any recourse or has any dynamic memory allocated. This is the last chance or place to free that memory or resource.
If for any reason your object failed to do that, there is a high risk of memory leak or resources will not be available for use further.
When an object goes out of scope or deleted, the sequence of events in its complete destruction is as follows(Ref):
The class's destructor is called, and the body of the destructor function is executed.
Destructors for nonstatic member objects are called in the reverse order in which they appear in the class declaration. The optional member initialization list used in the construction of these members does not affect the order of construction or destruction.
Destructors for non-virtual base classes are called in the reverse order of declaration.
Destructors for virtual base classes are called in the reverse order of declaration.
Before jumping to a virtual destructor, let's understand the issue we have without a virtual destructor.
Consider the below code:
Here we have a base class and a derived class that is inheriting base as public. In main we have a base pointer that is pointing to a derived class object. This is Upcasting.
Upcasting can cause object slicing when a derived class object is passed by value as a base class object
base::constructor derived::constructor base::destructor
If you run this program and observe, you will see only the destructor of the base class get called. What about derived class destructor?
It did not get called.
What is the problem here?
To understand the actual problem, consider the below code.
base::constructor derived::constructor Add: 015A5B10 value: 10 base::destructor ptr is pointing to 015A5B10 and value is 10
If you have noticed, the derived class has a pointer member variable that gets memory allocated dynamically in the derived class. We are deleting this dynamic memory in the derived class destructor.
In main(), to explain the point, there is an 'int *ptr' which is pointing to the memory held by derived class member variable 'x'.
When deleting b, the destructor of derived is not get called and the memory pointed by x is not freed. That's why still ptr is pointing to the same memory and contains