Do C++ destructors need to be defined as virtual? If so why? I've read that they need to be to ensure proper clean-up when one casts a base class pointer to a derived class.
A virtual destructor is required to allow dynamic dispatch of the destructor call to the proper class in the hierarchy tree.
In a situation in which you have:
Base *d = new Derived();
delete d;
without a virtual destructor you have undefined behavior. This because the compiler is not able to find the most specialized destructor for Derived, since it's not declared as virtual.
It is not required formally - you can easily compile a class with virtual functions but not a virtual destructor, but that's unwise.
Imagine you have a base class A, and two derived classes B and C. B and C have different fields and need different cleanup in destructor.
Now you assign
A *p = new B();
Then, when you call
delete p;
The compiler wouldn't know which destructor to call (actually this is an undefined behaviour according to the C++ standard).
If you don't define a virtual destructor, only the destructor of A could be called, which is not sufficient in the case of our hypothetical class B.
If you never instantiate your class with a new keyword (and afterwards delete it) you don't need a virtual destructor. However, adding a virtual destructor doesn't affect the performance, so it's best to always provide it.
Related
This question already has answers here:
When to use virtual destructors?
(20 answers)
Closed 3 years ago.
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
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
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.
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.
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.
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.
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.
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);
I was trying to familiarize myself with the OOP concepts but could not quite understand the concept of virtual.
One can create a virtual destructor but not a virtual constructor. Why?
How are virtual destructors handled internally? I mean the link Virtual Destructors illustrates the concept but my question is how the vptr of both the vtables (Derived and Base) are called? (In case of virtual member functions when such a scenario occurs generally the function that vptr of Derived class points to is only called)
Are there any other scenarios where one may need to use a virtual destructor?
Can anyone please help me understand the above concepts with links/examples?
First, a little about the difference between virtual functions and non-virtual functions:
Every non-virtual function-call that you have in your code can be resolved during compilation or linkage.
By resolved, we mean that the address of the function can be computed by the compiler or the linker.
So in the object code created, the function-call can be replaced with an op-code for jumping to the address of that function in memory.
With virtual functions, you have the ability to invoke functions which can be resolved only during runtime.
Instead of explaining it, let's run through a simple scenario:
class Animal
{
virtual void Eat(int amount) = 0;
};
class Lion : public Animal
{
virtual void Eat(int amount) { ... }
};
class Tiger : public Animal
{
virtual void Eat(int amount) { ... }
};
class Tigon : public Animal
{
virtual void Eat(int amount) { ... }
};
class Liger : public Animal
{
virtual void Eat(int amount) { ... }
};
void Safari(Animal* animals[], int numOfAnimals, int amount)
{
for (int i=0; i<numOfAnimals; i++)
animals[i]->Eat(amount);
// A different function may execute at each iteration
}
As you can probably understand, the Safari function allows you to be flexible and feed different animals.
But since the exact type of each animal is not known until runtime, so is the exact Eat function to be called.
The constructor of a class cannot be virtual because:
Calling a virtual function of an object is performed through the V-Table of the object's class.
Every object holds a pointer to the V-Table of its class, but this pointer is initialized only at runtime, when the object is created.
In other words, this pointer is initialized only when the constructor is called, and therefore the constructor itself cannot be virtual.
Besides that, there is no sense for the constructor to be virtual in the first place.
The idea behind virtual functions is that you can call them without knowing the exact type of the object with which they are called.
When you create an object (i.e., when you implicitly call a constructor), you know exactly what type of object you are creating, so you have no need for this mechanism.
The destructor of a base-class has to be virtual because:
When you statically allocate an object whose class inherits from the base-class, then at the end of the function (if the object is local) or the program (if the object is global), the destructor of the class is automatically invoked, and in turn, invokes the destructor of the base-class.
In this case, there is no meaning to the fact that the destructor is virtual.
On the other hand, when you dynamically allocate (new) an object whose class inherits from the base-class, then you need to dynamically deallocate (delete) it at some later point in the execution of the program.
The delete operator takes a pointer to the object, where the pointer's type may be the base-class itself.
In such case, if the destructor is virtual, then the delete operator invokes the destructor of the class, which in turn invokes the destructor of the base-class.
But if the destructor is not virtual, then the delete operator invokes the destructor of the base-class, and the destructor of the actual class is never invoked.
Consider the following example:
class A
{
A() {...}
~A() {...}
};
class B: public A
{
B() {...}
~B() {...}
};
void func()
{
A* b = new B(); // must invoke the destructor of class 'B' at some later point
...
delete b; // the destructor of class 'B' is never invoked
}
One can create a virtual destructor but not a virtual constructor. Why?
Virtual functions are dispatched according to the type of the object they're called on. When a constructor is called, there is no object - it's the constructor's job to create one. Without an object, there's no possibility of virtual dispatch, so the constructor can't be virtual.
How are virtual destructors handled internally?
The internal details of virtual dispatch are implementation-defined; the language doesn't specify the implementation, only the behaviour. Typically, the destructor is called via a vtable just like any virtual function.
how the vptr of both the vtables (Derived and Base) are called?
Only the most-derived destructor will be called virtually. All destructors, virtual or not, will implicitly call the destructors of all member and direct base-class subobjects. (The situation is slightly more complicated in the presence of virtual inheritance; but that's beyond the scope of this question).
Are there any other scenarios where one may need to use a virtual destructor?
You need one in order to support polymorphic deletion; that is, to be able to delete an object of derived type via a pointer to a base type. Without a virtual destructor for the base type, that's not allowed, and will give undefined behaviour.
because a Virtual function is invoked at runtime phase, however constructors are invoked at initialization phase, object is not constructed. So it's meaningless to have a virtual constructor.
a. the reason why only the base class desctructor is invoked in your link, the destructor is not marked as virtual, so the desctructor address is linked to Base class destructor at compile/link time, and obviously the type of the pointer is Base instead of Derived at compile time.
b. for why both of Base and Derived constructors are invoked after adding virtual to Base desctructor. It's same behavior like below:
Derived d; // when d exits the lifecycle, both Derived and Base's desctructor will be invoked.
Suppose when you have at least one virtual function, you should have a virtual desctructor.
One can create a virtual destructor but not a virtual constructor.
Why?
I'll try and explain this in layman's terms.
A class in c++ only exists after it's constructor completes. Each base class exists prior to initialisation of derived class and its members (vtable links included). Hence, having a virtual constructor does not make sense (since to construct, you need to know the type). Furthermore (in c++), calling virtual functions from a constructor does not work (as the derived class's vtable part has not been set up). If one thinks about it carefully, allowing virtual functions to be called from a contructor opens up a can of worms (such as what if virtual functions of derived classes are called prior to member initialization).
As far as destructors are concerned, at the point of destruction, the vtable is "intact", and we (c++ runtime) are fully aware of the type (so to speak). The destructor of the most derived part of the type is found (if virtual, through vtable), and therefore that destructor, and naturally that of all bases can be called.
How are virtual destructors handled internally? I mean the link
Virtual Destructors illustrates the concept but my question is how the
vptr of both the vtables (Derived and Base) are called?
Destructors are handled the same as normal virtual functions (that is, there addresses are looked up in a vtable if they are virtual at the expense of one (perhaps 2?) extra level/s of indirection). Furthermore, c++ guarantees that all base destructors shall execute (in opposite order of construction which relies on order of declaration) after completion of a derived destructor.
One can mimick/simulate virtual construction by using patterns such as the prototype pattern (or cloning), or by using factories. In such cases either an instance of the real type exists (to be used polymorphically), or a factory exists (deriving from abstract factory), that creates a type (via virtual function) based on some knowledge provided.
Hope this helps.
I assume we have a Base class A, and it's derived B.
1.: You can delete B via an A pointer, and then the correct method is to call the B destructor too.
However, you just can't say, that a B object should be created while you actually just call the A constructor. There is just not such a case.
You can say:
A* a = new B ();
or
B b;
But both directly call the B's constructor.
2.: Well, i am not entirely sure, but i guess it will iterate through the relevant part of the class hierarchy, and search for the closest call of the function. If a function is not virtual, it stop iterating and call it.
3.: You should always use virtual destructor, if you want to inherit something from that class. If it's a final class, you shouldn't.
I wasted a couple of days trying to discover why my derived virtual destructors were not being called before discovering the answer so hopefully I can save other a lot of grief with this reply.
I started using derived classes three and four levels deep in my project. Virtual functions seemed to work fine but then I discovered I had massive memory leaks because my destructors were not being called. No compiler or runtime error - the destructors just were not being called.
There is a ton of documentation and examples about this on the web but none of it was useful because my syntax was correct.
I decided that if the compiler wasn't going to call my destructors, I needed to create my own virtual destruct method to call. Then I got the compiler error that solved the problem - "class if a Forward Reference". Adding an include for the derived class header files in the base class solved the problem. The compiler needs the class definition to call the destructor!
I suggest when creating a new derived class, include the header file in the base and intermediate classes. Probably also a good idea to add conditional debug code to your destructors to check that they are bing called.
Bob Rice
Consider this code:
class A {
public:
void fun() {}
};
class B : public A {
public:
void fun() {}
};
int main()
{
A *p = new B;
delete p;
}
Classes A and B are not polymorphic, and neither class declares a destructor. If I compile this code with g++ -Wall, the GCC compiler happily compiles the code.
But if I add virtual to void fun() in A, the compiler issues this warning: "deleting object of polymorphic class type ‘A’ which has non-virtual destructor might cause undefined behavior".
I'm quite aware of the dangers of using non-virtual destructors. But the code above makes me wonder about two things:
Why do I need to write an empty virtual destructor in the base class when I'm not using destructors at all?
Why is the empty virtual destructor not required if the base class contains no other virtual functions?
EDIT
It appears that I need to clarify the thing that bothers me:
The above code declares no destructors.
If I declare a virtual function, the compiler complains about the missing virtual destructor. My conclusion: If the class is polymorphic, I need to write a virtual destructor if delete p is to work correctly.
But if I declare no virtual function (as in the initial example above), the compiler does not complain about a missing virtual destructor. My conclusion: If the class is not polymorphic, I do not need to write a virtual desctructor, and delete p will work correctly anyway.
But that last conclusion sounds intuitively wrong to me. Is it wrong? Should the compiler have complained in both cases?
Following up on PaulMcKenzie's and KerrekSB's comments, here is the answer to the two questions in the original post:
The class always has a destructor, even when the programmer doesn't explicitly write one. It is necessary to declare an empty virtual destructor in order to prevent the system from automatically generating a non-virtual one.
In the sample code provided, you do need a virtual destructor, even when there is no other virtual function in the class. The fact that GCC doesn't complain in this case is probably a bug in the compiler (or at least a shortcoming).
The background for this is found in §5.3.5 of the C++11 standard, which says, "if the static type of the object to be deleted is different from its dynamic type, the static type shall be a base class of the dynamic type of the object to be deleted and the static type shall have a virtual destructor or the behavior is undefined." (Italics mine.)
You are making an upcasting, in other words: a polymorphic use of the class B. If the class A has not virtual members, the compiler does not generate VTABLE for class A and it is not require a virtual destructor (note that your upcasting has no sense without polymorphism use). While if the class A declares virtual members, a VTABLE is generated by compiler, in this case you should provide a virtual destructor.
If your want polymorphic behaviour you need to define at least one virtual function in order compiler should generate v-table for your class.
Because C++ class contains two special functions (constructor and destructor) which used for every object it a good choice to make destructor virtual.
When you write delete p you really call a destructor for object associated with pointer p. If you not declare a destructor as virtual you've get error prone code.
Before your declare at least one of member function as virtual compiler did not expect that you intend using your class as polymorphic. In C++ phylosophy: "You should not pay for functionallity that you will never use". E.g. in simple case destructor should not be virtual.
I read that that virtual destructors must be declared in classes that have virtual methods. I just cant understand why they must be declared virtual. I know why we need to have virtual destructors as from the following example. I just wanted to know why compilers dont manage virtual destructors for us. Is there something I need to know about working of virtual destructors ?
The following example shows that if destructors are not declared virtual the destructors of derived class are not called why is that ?
class Base
{
// some virtual methods
public:
Base()
{std::cout << "Base Constructor\n";}
~Base()
{std::cout << "Base De-structor\n";}
};
class Derived : public Base
{
public:
Derived()
{std::cout << "Der constructor\n";}
~Derived()
{ std::cout << "Der De-structor\n";}
} ;
void main()
{
Base *b = new Derived();
delete b;
}
I just wanted to know why compilers dont manage virtual destructors for us.
Because in C++, you pay for what you use. Having a virtual destructor by default involves the compiler adding a virtual table pointer to the class, which increases its size. This is not always desirable.
The following example shows that if destructors are not declared virtual the destructors of derived class are not called why is that ?
The example exibits undefined behavior. It's simply against the rules. The fact that not all destructors are called is just one possible manifestation. It could possibly crash.
Is there something I need to know about working of virtual destructors ?
Yes. They are required if you're deleting an object through a pointer to a base class. Otherwise it's undefined behavior.
5.3.5 Delete [expr.delete]
3) In the first alternative (delete object), if the static type of the object to be deleted is different from its
dynamic type, the static type shall be a base class of the dynamic type of the object to be deleted and the
static type shall have a virtual destructor or the behavior is undefined. In the second alternative (delete
array) if the dynamic type of the object to be deleted differs from its static type, the behavior is undefined. (emphasis mine)
I read that that virtual destructors must be declared in classes that have virtual methods.
"must" is too strong a word: "should" fits much better into that advise.
I just wanted to know why compilers dont manage virtual destructors for us.
C++ designers tried to avoid compiler doing things that you did not ask it to do only under the most extreme circumstances. Language designers recognized that the decision to make a class polymorphic should rest with the designer of the program, so they refused to re-assign this responsibility to the compiler.
The following example shows that if destructors are not declared virtual the destructors of derived class are not called why is that?
Because your code is invalid: by declaring the destructor of Derived non-virtual you made a promise to never destroy Derived through a pointer to Base; your main breaks this promise, invoking undefined behavior.
Note that by merely declaring your b variable with the exact type you would have avoided the problem associated with the non-virtual destructor (link to ideone). However, this leads to a rather shaky design, so you should avoid inheritance hierarchies with virtual functions and non-virtual destructors.
I read that that virtual destructors must be declared in classes that have virtual methods.
Yes. But that is an oversimplification.
Its not that a class with virtual methods needs a virtual destructor. But the way a class with virtual methods is used means that it will usually need a virtual destructor. A virtual destructor is ONLY needed if you delete an object via a pointer to its base class. The problem is that when an object has virtually methods you are usually working with a pointer to its base class even though the actual object is slightly different.
I just cant understand why they must be declared virtual.
It's not that they must. As explained above. This is a result of the usual usage patterns.
I just wanted to know why compilers dont manage virtual destructors for us.
Because it is not always needed. And the ethos of C++ is you don't have to pay for something you don't need it. If the compiler always added virtual destructors to a class with virtual methods then I would have to pay the price of using a virtual destructor even in situations I can prove in my code base that I don't need it.
Is there something I need to know about working of virtual destructors ?
Just that there is a slight cost to using them.
if destructors are not declared virtual the destructors of derived class are not called why is that ?
That is why we have virtual destructors to cause this behavior. If you need this behavior you need to add virtual destructors. But there are cases were virtual destructors may not be required which allows the user of this method not to pay the price.
Do interfaces need a virtual destructor, or is the auto-generated one fine? For example, which of the following two code snippets is best, and why? Please note that these are the WHOLE class. There are no other methods, variables, etc. In Java-speak, this is an "interface".
class Base
{
public:
virtual void foo() = 0;
virtual ~Base() {}
};
OR...
class Base
{
public:
virtual void foo() = 0;
~Base() {} // This line can be omitted, but included for clarity.
};
EDIT DUE TO "NOT WHAT I'M LOOKING FOR" ANSWERS:
Exactly what are the consequences of each route. Please don't give vague answers like "it won't be destructed properly". Please tell me exactly what will happen. I'm a bit of an assembly nerd.
Edit 2:
I am well aware that the "virtual" tag means that the destructor won't get called if deleted through a pointer to derived, but (I think) this question ultimately boils down to "is it safe to omit that destructor, for is it truly trivial?"
EDIT 3:
My second edit is just plain wrong and disinformation. Please read the comments by actual smart people for more info.
Consider the following case:
Base *Var = new Derived();
delete Var;
You need the virtual destructor, otherwise when you delete Var, the derived class' destructor will never be called.
If you delete a derived class object via a base class pointer in C++, the result is undefined behaviour. UB is something you really want to avoid, so you must give base classes a virtual destructor. To quote from the C++ Standard, section 5.3.5:
if the static type of the operand is
different from its dynamic type, the
static type shall be a base class of
the operand’s dynamic type and the
static type shall have a virtual
destructor or the behavior is
undefined.
You should use a virtual destructor if you expect people to try to delete objects of a derived class via pointers or references of the parent class. If this is the case, then without a virtual destructor, the derived class will never be properly destructed.
For example,
Derived::~Derived() { // important stuff }
Base *foo = new Derived();
delete foo;
Without a virtual destructor in Base, Derived's destructor will never be called, and important stuff will therefore never happen.
Replying mostly to the edit:
Nobody can tell you what will happen because the result is "undefined behavior". When you delete a derived class through a pointer to a base that has no virtual destructor, the implementation is free to break down in any number of ways.
In general, a destructor should be either (1) public and virtual, or (2) protected and non-virtual.
Assuming you never expect anyone to delete a class instance via an interface pointer, a protected non-virtual destructor is 100% safe.
If someone tries to delete an interface pointer in case (2), they'll get a compile-time error.
No... virtual destructors are not auto generated. You have to declare them explicitely in your base class.
But you won't need to declare your destructors virtual for the child classes of Base. This is done by the compiler.
The compiler will also make sure that the destructors are called in reversed order of construction (from derived to base).
public class Base
{
//...
}
public class Derived
{
int i = 0;
//...
}
//...
Base* b = new Derived();
If you didn't have a virtual destructor
delete b;
would cause memory leaks (at least 4 bytes for the integer field), because it would destruct only Base and not Derived. The virtuality makes sure that the derived classes are destroyed, too. You won't have to declare a virtual constructor in Derived, this will be inferred by the compiler, if you declared a virtual destructor in Base.