I have a solid understanding of most OOP
theory but the one thing that confuses me a lot is virtual destructors.
I thought that the destructor always gets called no matter what and for every object in the chain.
When are you meant to make them virtual and why?
See this: Virtual Destructor
Every destructor down gets called no matter what.
virtual
makes sure it starts at the top instead of the middle.related question: When should you not use virtual destructors?
@MooingDuck that's somewhat misleading comment.
@EuriPinhollow Mind elaborating?
@FranklinYu it's good that you asked because now I can't see any issue with that comment (except trying to give answer in comments).
@FranklinYu I probably thought about that there should be more specific claim (i.e. when destruction can start in the middle of inheritance tree instead of top) but that's what answers already elaborate.
I'm also confused by @MooingDuck 's answer. Shouldn't it be up instead of down, if you use the notion of subclass (under) and superclass (above)?
@Nibor: Yes, if you use that notion. About half the people I talk to view superclasses as "above", and half view superclasses as "below", so both are conflicting standards, which makes everything confusing. I think superclass as "above" is slightly more common, but that's not the way I was taught 🙁
this article might help. medium.com/@tunvirrahmantusher/…
Make the destructor virtual whenever your class is polymorphic.
Virtual destructors are useful when you might potentially delete an instance of a derived class through a pointer to base class:
Here, you’ll notice that I didn’t declare Base’s destructor to be
virtual
. Now, let’s have a look at the following snippet:Since Base’s destructor is not
virtual
andb
is aBase*
pointing to aDerived
object,delete b
has undefined behaviour:In most implementations, the call to the destructor will be resolved like any non-virtual code, meaning that the destructor of the base class will be called but not the one of the derived class, resulting in a resources leak.
To sum up, always make base classes’ destructors
virtual
when they’re meant to be manipulated polymorphically.If you want to prevent the deletion of an instance through a base class pointer, you can make the base class destructor protected and nonvirtual; by doing so, the compiler won’t let you call
delete
on a base class pointer.You can learn more about virtuality and virtual base class destructor in this article from Herb Sutter.
Declare destructors virtual in polymorphic base classes. This is Item 7 in Scott Meyers’ Effective C++. Meyers goes on to summarize that if a class has any virtual function, it should have a virtual destructor, and that classes not designed to be base classes or not designed to be used polymorphically should not declare virtual destructors.
Also be aware that deleting a base class pointer when there is no virtual destructor will result in undefined behavior. Something that I learned just recently:
How should overriding delete in C++ behave?
I’ve been using C++ for years and I still manage to hang myself.
I like to think about interfaces and implementations of interfaces. In C++ speak interface is pure virtual class. Destructor is part of the interface and expected to implemented. Therefore destructor should be pure virtual. How about constructor? Constructor is actually not part of the interface because object is always instantiated explicitly.
A virtual constructor is not possible but virtual destructor is possible.
Let us experiment…….
The above code output the following:
The construction of derived object follow the construction rule but when we delete the “b” pointer(base pointer) we have found that only the base destructor is called. But this must not happen. To do the appropriate thing, we have to make the base destructor virtual.
Now let see what happens in the following:
The output changed as following:
So the destruction of the base pointer (which takes an allocation on derived object!) follows the destruction rule, i.e first the Derived, then the Base.
On the other hand, there is nothing like a virtual constructor.
What is a virtual destructor or how to use virtual destructor
A class destructor is a function with same name of the class preceding with ~ that will reallocate the memory that is allocated by the class. Why we need a virtual destructor
See the following sample with some virtual functions
The sample also tell how you can convert a letter to upper or lower
From the above sample you can see that the destructor for both MakeUpper and MakeLower class is not called.
See the next sample with the virtual destructor
The virtual destructor will call explicitly the most derived run time destructor of class so that it will be able to clear the object in a proper way.
Or visit the link
https://web.archive.org/web/20130822173509/http://www.programminggallery.com/article_details.php?article_id=138
I think the core of this question is about virtual methods and polymorphism, not the destructor specifically. Here is a clearer example:
Will print out:
Without
virtual
it will print out:And now you should understand when to use virtual destructors.
A basic definition about
virtual
is it determines if a member function of a class can be over-ridden in its derived classes.A class’s D-tor is called basically at the end of the scope, but there is a problem, for example when we define an instance on the Heap (dynamic allocation), we should delete it manually.
As soon as the instruction get executed, the base class destructor get called, but not for the derived one.
A Pratical example is when, in control field, you have to manipulate effectors, actuators.
At the end of the scope, if the destructor of one of the power elements (Actuator), isn’t called, there will be fatal consequences.
If you use
shared_ptr
(only shared_ptr, not unique_ptr), you don’t have to have the base class destructor virtual:output:
Virtual base class destructors are “best practice” – you should always use them to avoid (hard to detect) memory leaks. Using them, you can be sure all destructors in the inheritance chain of your classes are beeing called (in proper order). Inheriting from a base class using virtual destructor makes the destructor of the inheriting class automatically virtual, too (so you do not have to retype ‘virtual’ in the inheriting class destructor declaration).
I thought it would be beneficial to discuss the “undefined” behavior, or at least the “crash” undefined behavior that may occur when deleting through a base class(/struct) without a virtual destructor, or more precisely no vtable. The code below list a few simple structs (the same would be true for classes).
I’m not suggesting whether you need virtual destructors or not, though I think in general it’s a good practice to have them. I’m just pointing out the reason you may end up with a crash if your base class(/struct) does not have a vtable and your derived class(/struct) does and you delete an object via a base class(/struct) pointer. In this case, the address you pass to the heap’s free routine is invalid and thus the reason for the crash.
If you run the above code you’ll see clearly when the issue occurs. When the this pointer of the base class(/struct) is different from the this pointer of the derived class(/struct) you’re going to run into this problem. In the sample above, struct a and b don’t have vtables. structs c and d do have vtables. Thus an a or b pointer to a c or d object instance will be fixed up to account for the vtable. If you pass this a or b pointer to delete it will crash due to the address being invalid to the heap’s free routine.
If you plan to delete derived instances which have vtables from base class pointers, you need to ensure the base class has a vtable. One way to do that is to add a virtual destructor, which you might want anyway to properly clean up resources.
To be simple,
Virtual destructor is to destruct the resources in a proper order, when you delete a base class pointer pointing to derived class object.
Virtual keyword for destructor is necessary when you want different destructors should follow proper order while objects is being deleted through base class pointer.
for example:
If your base class destructor is virtual then objects will be destructed in a order(firstly derived object then base ). If your base class destructor is NOT virtual then only base class object will get deleted(because pointer is of base class “Base *myObj”). So there will be memory leak for derived object.
Calling destructor via a pointer to a base class
Virtual destructor call is no different from any other virtual function call.
For
base->f()
, the call will be dispatched toDerived::f()
, and it’s the same forbase->~Base()
– its overriding function – theDerived::~Derived()
will be called.Same happens when destructor is being called indirectly, e.g.
delete base;
. Thedelete
statement will callbase->~Base()
which will be dispatched toDerived::~Derived()
.Abstract class with non-virtual destructor
If you are not going to delete object through a pointer to its base class – then there is no need to have a virtual destructor. Just make it
protected
so that it won’t be called accidentally:Any class that is inherited publicly, polymorphic or not, should have a virtual destructor. To put another way, if it can be pointed to by a base class pointer, its base class should have a virtual destructor.
If virtual, the derived class destructor gets called and then the base class destructor. If not virtual, only the base class destructor gets called.
when you need to call derived class destructor from base class. you need to declare virtual base class destructor in base class.