I have a base class that is not polymorphic, but I want to prevent it from being instantiated.
Should I give this base class a pure virtual destructor to prevent it from being instantiated?
But is it wrong or bad practice to give a non-polymorphic base class a virtual destructor?
To prevent a base class from being instantiated make all constructors protected.
keep the ctor/dtor in protected scope.
Base classes in C++ are adviced to sport a virtual destructor. C++ is a really old programming language, and in case of not having a virtual destructor, an object of a derived class could be partially or incorrectly destroyed.
Certainly, a pure virtual destructor would prevent any instances of this class being created, but I think that, in order to make it clear that you don't expect this class to be instantiated, you could also create the constructors protected, as #Niels has pointed out in his answer.
Hope this helps.
Related
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.
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.
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
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.
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.