Should C++ 'interfaces' have a virtual destructor [duplicate] - c++

This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
Destructors for C++ Interface-like classes
Consider a simple example of a C++ abstract class, used to model an interface:
class IAnimal
{
virtual void walk()=0;
virtual ~IAnimal(){}
};
Is it better to have the destructor, or not? I don't think the destructor can be pure virtual, at least my tests give linker errors, so should an empty destructor be included?
EDIT: sorry, typo. It's a destructor not a constructor.

You should always use a virtual destructor with interfaces. Case in point:
IAnimal* animal = new Lion();
delete animal;
Now what destructor is it going to use? Definately not the Lion's destructor because the interface doesn't know about Lion's destructor.
So, have this if your interface has no memory management:
virtual ~IAnimal(){}

Check out this article by Herb Sutter
Especially this part:
For the special case of the destructor
only:
Guideline #4: A base class destructor
should be either public and virtual,
or protected and nonvirtual.
This assumes that base class is an 'interface' class as it mostly should be.

This depends on whether you intend to manage the lifetime of objects polymorphically, using pointers to the interface class.
If you do, then the destructor must be virtual, in order to correctly delete the objects. Deleting a base-class pointer that doesn't have a virtual destructor is invalid, and gives undefined behaviour.
If you don't, then you should enforce this by making the destructor non-virtual and protected, so only derived classes can be deleted.

I think it should be a pure virtual destructor for interfaces, and all other methods are pure virtual as well.

The only reason not to make the destructor virtual would be to save the space needed for the vptr. As you need the vptr anyway because you have another virtual function, I would make the destructor virtual.

an empty constructor should probably be included since a typical use of an interface involves putting a pointer to some concrete object in a container, which will otherwise call the wrong destructer and will not clean the memory correctly.
so if anyone is going to delete derived objects through a pointer to Ianimal make a virtual destructor, else make your destructor nonvirtual and protected.
making your destructor pure virtual is probably not such a good idea, since it forces implementers of derived classes to override your destructor, eventhough they might want to do nothing

Related

With virtual destructors, do I need to explicitly declare a virtual destructor for each subclass?

I've got a scenario where I'm writing somewhat deep object oriented code, with multiple layers of abstract base classes, and I'm wondering if I have to explicitly declare a destructor for each one.
Will the compiler generate a default one that's already virtual, or will I have to tell it to?
The default destructor is not virtual. If you declare the destructor of your base class as virtual, the destructors of the subclasses will be overrides, and thus also be virtual even without explicitly declaring them to be.
The GNU GCC compiler even gives a warning if you have a class hierarchy and your base class does not declare the destructor to be virtual because you most likely want it to be.
The answer is no. The only relevant requirement here is that classes with a vtable (i.e., with at least one virtual function) must have at least one a virtual destructor somewhere in their inheritance chain. Typically this means that your fundamental base class will provide an empty virtual destructor.
In general if some function is declared virtual in base class, there is no need to explicitly declare it virtual in subclasses. However it is good practice.
Declaring destructors in subclasses as virtual explicitly doesn't give you any serious advantages, so if you don't wont to write one more virtual, don't do that.

How/when do I use a virtual destructor?

I'm currently writing a program with the following polymorphic hierarchy: Base: Multinumber. Derived: Pairs, Complex, Rational. Multinumber is a virtual class and is never instantiated.
During the course of my program I frequently dynamically manage the base classes so I need a destructor. My question is this: how do I make the destructor virtual? In my Multinumber.h file right now I have this:
virtual ~Multinumber();
In my Multinumber.cpp:
Multinumber::~Multinumber()
{
}
And in all of my derived classes I have this:
Rational::~Rational()
{
}
I have nothing in any of my derived.h files. Unfortunately, this does not compile. Rather, I get this error:
Complex.cpp|75|error: definition of implicitly-declared 'virtual Complex::~Complex()'
What is wrong with my syntax? Thanks for any help you can give me.
Just declaring the virtual destructor in the base, and giving it the empty definition, is sufficient. For the other classes you do not need to do anything at all, unless there's actual work for those destructors to do.
The point of the virtual declaration in the base class is to ensure that the destructor can be invoked polymorphically (so that Base* d = new Derived(); delete d; works correctly, calling the Derived destructor instead of the Base destructor). You then have to define that destructor (even if it does no work) because you declared it.
However, for all of the derived classes, if you don't specify anything, the default "call destructors for members and bases" destructor gets generated for them, and everything works as you need it to. Unless, again, you need to do anything else to destruct the object properly.
As Dark Falcon noted, you need a declaration in the base for every member that you define, including destructors. So if you do write Complex::~Complex, then it must be declared in the Complex class definition, even though you inherit from a class that declares and defines a destructor. (Destructors, like constructors, aren't actually inherited anyway; the default "call recursively on members and bases" behaviour isn't really the same thing. These functions are special, since they manage the object lifetime, rather than using the object.)
Within the class Complex, you also need to have a declaration for the destructor:
~Complex();
Note that virtual is optional here. The destructor will be virtual because the base's destructor is virtual.
When to declare a destructor virtual?
I recommend you to follow this algorithm to decide whether you should declare a destructor virtual or not.
Is your class intended to be used as a base class?
No: Declare non-virtual destructor (avoids v-pointer on each object of the class) and remember not to derive from concrete classes.
Yes: Go to next question.
Is your base class abstract? (i.e. any virtual pure methods?)
No: Try to make you base class abstract by redesigning your hierarchy [1] (i.e. don't allow you base class to be instantiated).
Yes: Go to next question.
Do you want to allow polymorphic deletion though a base pointer?
No: Declare protected virtual destructor to avoid the unwanted usage.
Yes: Declare public virtual destructor (no overhead in this case).
References:
[1]: S. Meyers. More Effective C++, Item 33 (Addison-Wesley, 1996).
[2]: "Virtuality" http://www.gotw.ca/publications/mill18.htm
What is wrong with my syntax?
The following:
And in all of my derived classes I
have this:
Rational::~Rational() { }
No you don't. You didn't do it for Complex.
The question is: When to not declare the destructor virtual? There are no drawbacks to declaring a destructor virtual.

Should an abstract class' destructor be pure virtual?

I think virtual alone is generally sufficient.
Is there another reason to make it pure virtual than to force derived classes to implement their own destructor? I mean if you allocate something in your class' constructor you should impement your own destructor - if your class is derived or not.
Doesn't count as answer as I already know: If you want your class abstract and it has no pure virtual functions - leave it to the destructor.
Some more uses?
If you want your class abstract and it
has no pure virtual functions - leave
it to the destructor.
Actually, I don't think there's more. All the pure virtual destructor does, is make the whole class abstract. You have to provide the implementation for the pure virtual destructor as well as for a non-pure virtual destructor, the destructors of the derived classes are virtual with virtual destructor alone, etc.
Basically, if a class has already some pure virtual functions, its behaviour would be equivalent with virtual and pure-virtual destructor.
No. If the base class allocates anything, it is it's responsiblity to release it.
Further, if the derived class does not allocte anything, there's no point in forcing them to write a dummy dtor.
Ideally the language should have a way to assure (implicitly or not) that the destructor is virtual in abstract classes without having to define it or make it pure. But it hasn't.
So the choice is: either make it pure, and have the burden of defining it in each derived class, or make it not, and have the burden of defining it in the abstract class. The later is less work, and also shorter code, so I'd go for it.
If your abstract class is a pure interface, with no data members than you could get along with making the dtor pure virtual. I prefer that myself, since I've seen so many hot-shot programmers forget to make a virtual destructor at all: Even when they write derived classes containing virtual methods.
So I would do it purely to minimize maintenance headaches down the road.

Destructor of a concrete class

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.
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.
If nothing else in your class is virtual, I don't think the destructor should be virtual either.
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.
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.
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).
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.

Can the default destructor be generated as a virtual destructor automatically?

Can the default destructor be generated as a virtual destructor automatically?
If I define a base class but no default destructor, is there a default virtual destructor
generated automatically?
No. There is a cost associated with making a method virtual, and C++ has a philosophy of not making you pay for things that you don't explicitly state that you want to use. If a virtual destructor would have been generated automatically, you would have been paying the price automatically.
Why not just define an empty virtual destructor?
In C++ 11 you can use:
class MyClass
{
// create a virtual, default destructor
virtual ~MyClass() = default;
};
Yes, by inheriting from a base class with a virtual destructor. In this case, you already pay the price for a polymorphic class (e.g. vtable).
No, all destructor's are by default NOT virtual.
You will need to define a virtual destructor on all the base classes
In addition to that.
To quote Scott Meyers in his book "Effective C++":
The C++ language standard is
unusually clear on this topic. When
you try to delete a derived class
object through a base class pointer
and the base class has a non-virtual
destructor (as EnemyTarget does), the
results are undefined
In practice, it's usually a good idea to define a class with a virtual destructor if you think that someone might eventually create a derived class from it. I tend to just make all classes have virtual destructor's anyway. Yes, there is a cost associated with that, but the cost of not making it virtual more often that not out weighs a measly bit of run-time overhead.
I suggest, only make it non-virtual when you're absolutely certain that you want it that way rather than the rely on the default non-virtual that the compilers enforce. You may disagree, however (in summary) I recently had a horrid memory leak on some legacy code where all I did was add a std::vector into one of the classes that had existed for several years. It turns out that one of it's base classes didn't have a destructor defined (default destructor is empty, non-virtual!) and as no memory was being allocated like this before no memory leaked until that point. Many days of investigation and time wasted later...
Uri and Michael are right -- I'll just add that if what's bugging you is having to touch two files to declare and define the destructor, it's perfectly all right to define a minimal one inline in the header:
class MyClass
{
// define basic destructor right here
virtual ~MyClass(){}
// but these functions can be defined in a different file
void FuncA();
int FuncB(int etc);
}
Currently, Uri is right. On the other hand, after you have declared a virtual method in your class, you are paying the price for the existence of the virtual table anyway. In fact, the compiler will warn you if your class has a virtual method, but no virtual destructor. This could become a candidate for automatic generation of the default virtual destructor instead of the pesky warning.
No. You need to declare it as virtual.
Some people stated that it is never defaulted to virtual. That's not exactly true.
Even though destructors are not inherited, if a base class declares its destructor virtual, the derived destructor always overrides it.
This means that if the base class has a virtual destructor you don't have to define a destructor of the derived class as virtual nor explicitly write:
/// All of these are unnecessary and won't change the destruction behavior
/// as long as Class inherits from a base class with a virtual destructor
virtual ~Class() = default;
// or
~Class() override = default;
// or
~Class() {}