Is there ever a good reason to not declare a virtual destructor for a class? When should you specifically avoid writing one?
Virtual keyword for destructor is necessary when you want different destructors should follow proper order while objects is being deleted through base class pointer.
A virtual destructor is used to free up the memory space allocated by the derived class object or instance while deleting instances of the derived class using a base class pointer object.
CPP. Making base class destructor virtual guarantees that the object of derived class is destructed properly, i.e., both base class and derived class destructors are called. For example, CPP.
A C++ class containing virtual member functions has a non-virtual destructor. Since this class has virtual member functions, it will be used as a base class. The use of non-virtual destructors in base classes is dangerous because it can cause objects to be torn down incorrectly.
There is no need to use a virtual destructor when any of the below is true:
No specific reason to avoid it unless you are really so pressed for memory.
To answer the question explicitly, i.e. when should you not declare a virtual destructor.
C++ '98/'03
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.
struct A {
// virtual ~A ();
int i;
int j;
};
void foo () {
A a = { 0, 1 }; // Will fail if virtual dtor declared
}
In an extreme case, such a change can also cause undefined behaviour where the class is being used in a way that requires a POD, e.g. passing it via an ellipsis parameter, or using it with memcpy.
void bar (...);
void foo (A & a) {
bar (a); // Undefined behavior if virtual dtor declared
}
[* 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.]
Modern C++
In recent versions of C++, the concept of POD was split between the class layout and its construction, copying and destruction.
For the ellipsis case, it is no longer undefined behavior it is now conditionally-supported with implementation-defined semantics (N3937 - ~C++ '14 - 5.2.2/7):
...Passing a potentially-evaluated argument of class type (Clause 9) having a non-trivial copy constructor, a non-trivial move constructor, or a on-trivial destructor, with no corresponding parameter, is conditionally-supported with implementation-defined semantics.
Declaring a destructor other than =default
will mean it's not trivial (12.4/5)
... A destructor is trivial if it is not user-provided ...
Other changes to Modern C++ reduce the impact of the aggregate initialization problem as a constructor can be added:
struct A {
A(int i, int j);
virtual ~A ();
int i;
int j;
};
void foo () {
A a = { 0, 1 }; // OK
}
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With