tags:

views:

1588

answers:

9

Is there ever a good reason to not declare a virtual destructor for a class? When should you specifically avoid writing one?

+22  A: 

There is no need to use a virtual destructor when any of the below is true:

  • No intention to derive classes from it
  • No instantiation on the heap
  • No intention to store in a pointer of a superclass

No specific reason to avoid it unless you are really so pressed for memory.

sep
fine overview. i dropped my answer in favour of this. +1 :)
Johannes Schaub - litb
This is not a good answer. "There is no need" is different from "should not", and "no intention" is different from "made impossible".
Windows programmer
Also add: no intention to delete an instance via a base class pointer.
Adam Rosenfield
This doesn't really answer the question. Where is your good reason not to use a virtual dtor?
Max Howell
I think that when there is no need to do something, that is a good reason not to do it. Its following the Simple Design principle of XP.
sep
By saying you have "no intention", you're making a huge assumption about how your class will get used. It seems to me the simplest solution in most cases (which should therefore the default) should be to have virtual destructors, and only avoid them if you have a specific reason not to. So I'm still curious about what would be a good reason.
ckarras
+13  A: 

I declare a virtual destructor if and only if I have virtual methods. Once I have virtual methods, I don't trust myself to avoid instantiating it on the heap or storing a pointer to the base class. Both of these are extremely common operations and will often leak resources silently if the destructor is not declared virtual.

Andy
And, in fact, there is a warning option on gcc which warns on precisely that case (virtual methods but no virtual dtor).
CesarB
Don't you then run the risk of leaking memory if you derive from the class, regardless of whether you have other virtual functions?
Mag Roader
+2  A: 

A virtual destructor is needed whenever there is any chance that delete might be called on a pointer to an object of a subclass with the type of your class. This makes sure the correct destructor gets called at run time without the compiler having to know the class of an object on the heap at compile time. For example, assume B is a subclass of A:

A *x = new B;
delete x;     // ~B() called, even though x has type A*

If your code is not performance critical, it would be reasonable to add a virtual destructor to every base class you write, just for safety.

However, if you found yourself deleteing a lot of objects in a tight loop, the performance overhead of calling a virtual function (even one that's empty) might be noticeable. The compiler cannot usually inline these calls, and the processor might have a difficult time predicting where to go. It is unlikely this would have a significant impact on performance, but it's worth mentioning.

Jay Conrod
A: 

The performance answer is the only one I know of which stands a chance of being true. If you've measured and found that de-virtualizing your destructors really speeds things up, then you've probably got other things in that class that need speeding up too, but at this point there are more important considerations. Some day someone is going to discover that your code would provide a nice base class for them and save them a week's work. You'd better make sure they do that week's work, copying and pasting your code, instead of using your code as a base. You'd better make sure you make some of your important methods private so that no one can ever inherit from you.

Windows programmer
Polymorphism will certainly slow things down. Compare it with a situation where we need polymorphism and choose not to, it will be even slower. Example: we implement all the logic at the base class destructor, using RTTI and a switch statement to clean up resources.
sep
In C++, it's not your responsibility to stop me inheriting from your classes that you've documented are not suitable for use as base classes. It's my responsibility to use inheritance with caution. Unless house style guide says otherwise, of course.
Steve Jessop
... just making the destructor virtual doesn't mean the class will necessarily work correctly as a base class. So marking it virtual "just because", instead of making that assessment, is writing a check my code can't cash.
Steve Jessop
+1  A: 

I usually declare the destructor virtual, but if you have performance critical code that is used in an inner loop, you might want to avoid the virtual table lookup. That can be important in some cases, like collision checking. But be careful about how you destroy those objects if you use inheritance, or you will destroy only half of the object.

Note that the virtual table lookup happens for an object if any method on that object is virtual. So no point in removing the virtual specification on a destructor if you have other virtual methods in the class.

Jørn Jensen
+16  A: 

To answer the question explicitly, ie. when should you not declare a virtual destructor.

Adding a virtual destructor might change your class from being POD (Plain Old Data)* or Aggregate to Non-POD. This can stop your project from compiling if your class type is aggregate initialized somewhere.

In an extreme case, such a change can also cause undefined behaviour where the class is being used n a way that requires a POD, eg. passing it via an ellipsis parameter, or using it with memcpy.

* A POD type is a type that has specific guarantees about its memory layout. The standard really only says that if you were to copy from an object with POD type into an array of chars (or unsigned chars) and back again, then the result will be the same as the original object.]

Richard Corden
You're right, and I was wrong, performance isn't the only reason. But this shows I was right about the rest of it: the class's programmer had better include code to prevent the class from ever being inherited by anyone else.
Windows programmer
Hmm... I agree with this point also.
sep
+2  A: 

Virtual functions mean every allocated object increases in memory cost by a virtual function table pointer.

So if your program involves allocating a very large number of some object, it would be worth avoiding all virtual functions in order to save the additional 32 bits per object.

In all other cases, you will save yourself debug misery to make the dtor virtual.

Max Howell
+1  A: 

Not all C++ classes are suitable for use as a base class with dynamic polymorphism.

If you want your class to be suitable for dynamic polymorphism, then its destructor must be virtual. In addition, any methods which a subclass could conceivably want to override (which might mean all public methods, plus potentially some protected ones used internally) must be virtual.

If your class is not suitable for dynamic polymorphism, then the destructor should not be marked virtual, because to do so is misleading. It just encourages people to use your class incorrectly.

Here's an example of a class which would not be suitable for dynamic polymorphism, even if its destructor were virtual:

class MutexLock {
    mutex *mtx_;
public:
    explicit MutexLock(mutex *mtx) : mtx_(mtx) { mtx_->lock(); }
    ~MutexLock() { mtx_->unlock(); }
private:
    MutexLock(const MutexLock &rhs);
    MutexLock &operator=(const MutexLock &rhs);
};

The whole point of this class is to sit on the stack for RAII. If you're passing around pointers to objects of this class, let alone subclasses of it, then you're Doing It Wrong.

Steve Jessop
Polymorphic use doesn't imply polymorphic deletion. There are plenty of use cases for a class to have virtual methods yet no virtual destructor. Consider a typical statically defined dialog box, in pretty much any GUI toolkit. The parent window will destroy the child objects, and it knows the exact type of each, yet all the child windows will also be used polymorphically in any number of places, such as hit testing, drawing, accessibility APIs that fetch the text for text-to-speech engines, etc.
Ben Voigt
True, but the questioner is asking when you should specifically avoid a virtual destructor. For the dialog box you describe, a virtual destructor is pointless, but IMO not harmful. I'm not sure I'd be confident that I'll never need to delete a dialog box using a base class pointer - for example I may in future want my parent window to create its child objects using factories. So it's not a question of *avoiding* virtual destructor, just that you might not bother having one. A virtual destructor on a class not suitable for derivation *is* harmful, though, because it's misleading.
Steve Jessop
+1  A: 

If you have a very small class with a huge number of instances, the overhead of a vtable pointer can make a difference in your program's memory usage. As long as your class doesn't have any other virtual methods, making the destructor non-virtual will save that overhead.

Mark Ransom