When should your destructor be virtual?
Solution 1
- You need virtual destructor when at least one of class methods is virtual.
This is because the reason for virtual method is that you want to use polymorphism. Meaning you will call a method on the base class pointer and you want the most derived implementation - this is the whole point of polymorphism.
Now if you did not have virtual destructor and through the pointer to base class you call destructor you end up calling base class destructor. In this case you want polymorphism to work on your destructor as well, e.g. through calling destructor on your base class you want to end up calling destructor of your most derived class not your base class.
class A
{
virtual void f() {}
~A() {}
}
class B : public A
{
void f() {}
~B() {}
}
A * thing = new B();
thing->f(); // calls B's f()
delete thing; // calls ~A(), not what you wanted, you wanted ~B()
having ~A() virtual turns on polymorphism
virtual ~A() {}
So when you now call
delete thing;
~B() will be called.
You would declare virtual destructors when you design class as an interface e.g. you expect it to be extended or implemented. A good practice in that case is to have a interface class (in the sense of Java interfaces) with virtual methods and virtual destructor and then have concrete implementation classes.
You can see that STL classes don't have virtual destructors so they are not supposed to be extended (e.g. std::vector, std::string ...). If you extend std::vector and you call destructor on base class via pointer or reference you will definitely not call your specialized class destructor which may lead to memory leaks.
Solution 2
From Stroustrup's C++ Style and Technique FAQ:
So when should I declare a destructor virtual? Whenever the class has at least one virtual function. Having virtual functions indicate that a class is meant to act as an interface to derived classes, and when it is, an object of a derived class may be destroyed through a pointer to the base.
Lots of additional info on when your destructor should be virtual on the C++ FAQ. (thanks Stobor)
What is a virtual member? From the C++ FAQ:
[20.1] What is a "virtual member function"?
From an OO perspective, it is the single most important feature of C++: [6.9], [6.10].
A virtual function allows derived classes to replace the implementation provided by the base class. The compiler makes sure the replacement is always called whenever the object in question is actually of the derived class, even if the object is accessed by a base pointer rather than a derived pointer. This allows algorithms in the base class to be replaced in the derived class, even if users don't know about the derived class.
The derived class can either fully replace ("override") the base class member function, or the derived class can partially replace ("augment") the base class member function. The latter is accomplished by having the derived class member function call the base class member function, if desired.
Solution 3
I've recently come to conclude that the fully correct answer is this:
Guideline #4: A base class destructor should be either public and virtual, or protected and nonvirtual.
And of course Herb Sutter gives the rationale to his claim. Note that he does go beyond the usual answers "when someone will delete a derived-class object via a base-class pointer" and "make your destructor virtual if your class has any virtual functions".
Solution 4
If you will (or even might) destroy objects of a derived class through a base class pointer, you need a virtual destructor.
I take the approach that if I'm going to derive from a class AT ALL, then it shall have a virtual destructor. There are effectively no cases in the code I write where the performance implications of a virtual destructor matter, and even if it's not actually needed today, it might end up needing it in the future when the class is modified.
Basically: Put virtual on all base class destructors unless you have a good, well-thought out reason not to.
That's just another rule of thumb, but it's one that keeps you from making later mistakes.
Related videos on Youtube
Comments
-
Michael Zhou almost 4 years
Possible Duplicate:
When to use virtual destructors?When should your C++ object's destructor be
virtual
?-
Stobor almost 15 yearsCopied from <blogs.msdn.com/oldnewthing/archive/2004/05/07/127826.aspx >?
-
aJ. almost 15 yearslot of related stuff: stackoverflow.com/search?q=virtual+destructor
-
Tunvir Rahman Tusher about 11 yearstry this link stackoverflow.com/questions/461203/… .It might help
-
-
Nubzor almost 15 years+1 nice copy paste quote from Mr S., can't really beat that answer
-
Stobor almost 15 years
-
Tom Leys almost 15 yearsIn that case, Stobor, there was little point instantiating the derived class. There is no way to access the derived class's methods without a dynamic_cast, which implies knowledge of the object type. That knowledge could be used to dynamic_cast before the destructor too. Of course, the virtual method thing is just a rule of thumb. Not surprising your contrived example shoots a hole in it
-
hookenz almost 15 yearsThis is not quite correct e.g. If a base class A (non virtual destructor defined) doesn't have resources, and class B (a subclass of A) does have resources and we have something like B *b = new B(); A *a = static_cast<A>(b); delete a; then the result is actually undefined in the standard. It might free the resources, or it might not. More often than not memory is leaked. So the correct answer would be - if you've got sub-classes, then the base class needs to have a virtual destructor to ensure resources are correctly freed.
-
Tom almost 15 yearsC++ didn't give you that flexibility just so you could throw it away. Put another way, "Unless I'm really concerned with the storage and performance overhead of a vtable, I'm going to use an easier language like Python or Lua."
-
Steve Jessop almost 15 yearsIn the astonishingly rare situation where Stroustrup's deduction doesn't hold (i.e. the class is intended to act as an interface to derived classes, but the desired interface is that an object of a derived class MAY NOT be destroyed through a pointer to the base) then IIRC you can have a protected non-virtual destructor. It's next to pointless making it non-virtual AFAIK, since virtual destructors are hardly a common performance bottleneck. But stopping clients from deleting stuff themselves might be a useful restriction, and it could then be non-virtual if desired.
-
gbjbaanb almost 15 years@Tom: yes, you can just throw the flexibility away. C++ gives you the flexibility so you can remove it when you want, or add it when you want. Lesser languages enforce it all the time. So for C++, you might as well put virtual dtors everywhere, except in those cases where you've thought about it and decided you don't want them.
-
Nubzor almost 15 yearsI would not narrow it down to those 2 options. You use tools to build what is required, in this case features of programming language. If you create every public destructor public you turn on polymorphism for each of those classes, probably in 90% of those cases you don't need that and you end up with unnecessary overhead.
-
sebkraemer over 4 yearsThe exact answer I was looking for after choosing the wrong answer in the pluralsight skill IQ question, thanks
-
Marine Galantin over 3 yearsit has been included in the guidelines : C.35 : github.com/isocpp/CppCoreGuidelines/blob/master/…