5

Based on what I found here and on other links on stackoverflow, we should always define a virtual destructor in the base class if we plan to use it polymorphically. I want to know if there is an exception to this rule.

I have seen production code that does not define virtual destructor for the pure abstract base classes and in one of cppcon 2014 video Accept no visitor, around 10:06 the BoolExp struct defined is a pure abstract class and has no virtual destructor.

So for a pure abstract class defined like this

  class Base {
      public:
         virtual foo() = 0;
         virtual bar() = 0;
     }

My question is it absolutely must that we define a virtual destructor for "Base" class, even though it does have any data members? Are there any exceptions to the virtual destructor rule?

Thanks in advance.

Best, RG

DDG
  • 147
  • 1
  • 6

7 Answers7

6

My question is it absolutely must that we define a virtual destructor for "Base" class, even though it does have any data members?

It depends. If you have a case like

base * foo = new child(stuff);
// doing stuff
delete foo;

then you absolutely must have a virtual destructor. Without it you'll never destroy the child part.

If you have a case like

child * foo = new child(stuff);
// doing stuff
delete foo;

Then you do not need a virtual destructor, as child's will be called.

So the rule is if you delete polymorphically, you need a polymorphic (virtual) destructor, if not, then you don't

NathanOliver
  • 171,901
  • 28
  • 288
  • 402
1

The exception to the rule is if you never delete an object through a pointer to the base class. In that case the base class destructor does not need to be virtual.

But if you ever delete an object via a base class pointer, then the base class destructor must be virtual or your program has Undefined Behaviour.

Jesper Juhl
  • 30,449
  • 3
  • 47
  • 70
1

My question is it absolutely must that we define a virtual destructor for "Base" class, even though it does have any data members?

Stricktly speaking, No.

However, whether the base class has any member variables is not relevant. If the destructor gets called using a pointer to the base class, your code has undefined behavior regardless of whether the base class has any member variables or not.

Are there any exceptions to the virtual destructor rule?

If you are able to manage lifetimes of derived classes in such a way that the call to delete the objects is done via derived class pointers, you don't invoke undefined behavior and your code will be well behaved, assuming everything else is in your code base is in good order.

R Sahu
  • 204,454
  • 14
  • 159
  • 270
1

we should always define a virtual destructor in the base class if we plan to use it polymorphically.

You should always define a virtual destructor in a base classs if we plan to delete it polymorphically through that base class.

Now, one problem is that "I don't intend to" isn't safe; you should make it impossible.

Make the destructor virtual (and empty), or make it protected (and empty). A protected destructor makes polymorphic deletion unlikely (it can be bypassed, but only through pretty insane means).

Barring that, you have to be careful. This is one of the reasons why inheriting from (say) std vector is a thing to be wary of.

Yakk - Adam Nevraumont
  • 262,606
  • 27
  • 330
  • 524
0

Deleting a derived class object using a pointer to a base class that has a non-virtual destructor results in undefined behavior. 

Otherwise you are ok to not to have virtual destructor.

Oblivion
  • 7,176
  • 2
  • 14
  • 33
0

is it absolutely must that we define a virtual destructor for "Base" class, even though it does have any data members? Are there any exceptions to the virtual destructor rule?

It is not a must. It's a good habit that can prevent bugs.

If you decide to create a base class that doesn't have a virtual destructor, it is the responsibility of you, the developer, to always ensure that derived objects are deleted as the correct type or as a base type that does have a virtual destructor.

Drew Dormann
  • 59,987
  • 13
  • 123
  • 180
0

I would like to make an important (at least, in my view) practical amendment to correct answers describing the deletion through base object.

In particular, the destructors are called non-virtually if object life-time is managed through std::shared_ptr<Base> allocated via

std::shared_ptr<Base> sptr = std::make_shared<Derived>(args);
SergeyA
  • 61,605
  • 5
  • 78
  • 137