views:

162

answers:

6

Guideline #4 link text, states:

A base class destructor should be either public and virtual, or protected and nonvirtual.

Probably I'm missing something, but what if I just create a concrete class, that is not designed to be used as base class.

Should I declare it's destructor public and virtual? By this I'm implicitly declate that my class is "ready to be used as base class", while this is not necessary true.

A: 

If nothing else in your class is virtual, I don't think the destructor should be virtual either.

Rasmus Kaj
A: 

Your destructor only needs to be virtual if your class will be extended later. I'm not aware of a case where you'd want a protected/private destructor.

It's worth noting that if you have even one virtual method, you lose nothing (with most compilers) making the destructor virtual as well (but it will protect you in case somebody extends later).

Stephen Newell
"Your destructor only needs to be virtual if it will be extended later." That's actually wrong. A dtor should be virtual when objects of derived classes will be deleted through base class pointers. Not doing so yields undefined behaviour, no matter whether the derived class' dtor is user-defined or compiler-generated.
sbi
@sbi: "Extended" generally means "derived from", so I don't see any disagreement here. If a class will be derived from, I'd expect it to be used polymorphically sometime, and then a virtual destructor would be necessary. If it isn't, then it can't be used polymorphically, and doesn't need a virtual destructor.
David Thornley
@sbi: I see my verbiage is a little confusing. I did not mean if the a base class provides an explicit dtor, I meant the class itself was extended. I'll edit my answer to reflect that. Thanks.
Stephen Newell
+5  A: 

The link text specifically says"A base class destructor should be"...

The guidelines are only meant for a class which is designed to be used as a base class. If you are making a single, concrete class that will not be used as a base class, you should leave the public constructor non-virtual.

Reed Copsey
Upps, you're right - the answer is in the question body :)
dimba
A: 

Consider it another way around: Do you know that no one will absolutely ever try to derive from your class and when somebody does do you think he will remember to take a closer look at your dtor? Sometimes people use inheritance over composition for a good reason (provide the full interface of your class without having ugly getter syntax).
Another point for the virtual dtor is the Open/Closed Principle.
I'd go with the virtual dtor if you are not concerned with hard real-time performance or something alike.

pmr
A: 

Destructor SHALL BE virtual in any of the following cases:

  • Your class contains ANY virtual method.
  • Even if nothing is virtual you plan to use class as base.

Rare exception:

  • You are trying to save 4 bytes and virtual table pointer is NOT ACCEPTABLE solution because of this (example - your class HAS to fit in 32 bits because of some reason). But be prepared for hell.

Regarding public or protected - in general it is more question of how you intend to control access to destructor.

Roman Nikitchenko
Exception 2: The new operator on the class is private. -- Stack based objects can't be sliced without causing other errors.
jmucchiello
+1 on comment with "new" operator but I have no real experience for this monkey trick. Could you point to more detailed explanation / example ?
Roman Nikitchenko
Stack-based objects can't end up with the wrong destructor being called, full stop. If you construct a base class object from a derived class object on the stack, then the derived destructor will still be called for that stack object (and the base destructor will be called for the base class object, if it's also stack-based). Even binding temporaries to references works fine: `const Base `, the derived destructor will be called on the temporary when b leaves scope, regardless of whether either destructor is virtual.
Steve Jessop
A: 

The advice refers to classes with virtual functions, intended to be polymorphic base classes. You have to make sure that if someone calls delete on a base class pointer, then the destructor of the actual class is called; otherwise, resources allocated by the derived classes won't be freed.

There are two ways to achieve this:

  • a public virtual destructor, so the correct destructor is found at runtime; or
  • a protected non-virtual destructor, which prevents calling delete on a base class pointer.

For a concrete class that won't be used as a base class, you will only ever call delete on a pointer to the actual type, so the advice doesn't apply. It should have a public non-virtual destructor if it needs one.

Mike Seymour