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.
Related
Suppose I have:
struct Base
{
/**/ virtual /**/ ~Base() {/*..*/}
// ...
};
struct Derived : Base
{
~Derived() /* override */ {/*..*/}
// ...
};
When a class inherits from another class, overriding is here to help me to make sure I'm implementing a function that actually exists in Base.
In this scenario described above, Derived class has a different name from Base, and therefore its destructor is written differently.
My question is, in case I want to use override, where shall I use that?
Where do I really implement a Base's function in Derived class?
First of all "override" keyword simply means "this function is marked as virutal in some base class", nothing else. And it can be applied to destructors as well. Destructors however are special, normal rules don't apply to them. For example destructor in Derived, named ~Derived() is matched with destructor in Base, named ~Base(), even though formally they have different names (or do they? what is a name here anyway?).
Another difference between destructors and typical functions is that destructors are always called up the inheritance chain, regardless of implementation. And so you cannot "replace" destruction, you can only "extend" it. Note that (unlike normal functions) calling base class destructor from derived destructor is a mistake.
The chained destruction call starts at the class you are refering to at the moment. What I mean is
Base* inst = new Derived();
delete inst;
will call ~Base() because the variable inst is Base* even though it was constructed from a derived class. At this point "virtual logic" applies: if ~Base() is not virtual then normal destruction procedure fires for Base class, without being aware that the actual object is Derived*, i.e. ~Base() and all its parent desctuctors (there are none in this particular case) are executed. Which is wrong. But if it is virtual then it will actually jump to the correct class, Derived, and the correct destruction procedure is invoked: first ~Derived(), then ~Base(). See this godbolt.org and play around: add and remove "virtual" in base destructor to see the difference (look at the left column only, lines with colored background are those that are actually called).
All in all: yes, you can use ~Derived() override {}. I always use "override" where appropriate, it's nice to know which functions are derived from virtuals. Also the rule of thumb is: if Base is virtual (meaning any function is virtual) then its destructor should be virtual as well. Remember this well and it will help you avoid some problems.
As far as I know, some of C++ linter tools (like clang-tidy) already have a checking mode that could complain that your derived class doesn't mark derived virtual destructor with "override" clause. So yes, despite the fact you're not obliged to do so (according to 12.4.9 chapter of C++ Standard), you could explicitly apply "override" to catch a situation once your base class is not virtual-destructible anymore but derived classes intend to still have that.
And, yeah, just do not worry about difference is destructor names (it is a syntax catch, not more) and thing of it as void ~() method.
In many sources, books etc. are written "don't call this->virtualFunction in child class constructor" and in some sources explain why you mustn't do it. Because at the moment of construction class isn't created at all. So virtual function that will be called from child constructor will be function of base class. It means that in child constructor body VPTR of that class pointed to base VTABLE.
So my question is,
what is the moment in object construction when VPTR of child class will be overriden to address on it's virtual table? I guess that some automatically generated code do it at end of constructor body or after constructor body will be executed.
And second question is,
why is VPTR overriden at the end of construction? Maybe for it have some important reasons?
Why can't override VPTR at beginning constructor body or after base class constructed?
Child::Child() :
Base()
//<----- Why not here?
//members initialization
{
//<----- Why not here?
//code
}
In many sources, books etc. are written "don't call this->virtualFunction in child class constructor"
I doubt that. It's often advised not to call virtual functions from the base class constructor, to avoid confusion if you expect them to call the final overrides, not the base-class versions. And you must certainly not call them from the base class if they are pure virtual there - that gives undefined behaviour.
Within the derived class constructor, they are well-defined and do what you would expect.
So virtual function that will be called from child constructor will be function of base class.
No, during the child's constructor body, the dynamic type is Child, and virtual functions calls will use the Child overrides.
what is the moment in object construction when VPTR of child class will be overriden to address on it's virtual table?
After all base class constructors have completed, and before child class members are initialised. Child member functions, including virtual functions, can be called from member initialisers (but not base class initialisers) or the constructor body.
You need to be careful calling them from member initialisers, since they might access uninitialised members. But within the constructor body, all base objects and members are initialised, so they are quite safe.
why is VPTR overriden at the end of construction?
It isn't. It happens at the first point you indicate with <----- Why not here?.
I disagree with your overly simplified reason to why you shouldn't call a virtual function. First of all, a VTABLE is not actually defined by the C++ standard, and is, in fact, implementation specific:
When is VTable in C++ created?
Calling a virtual function from a constructor is allowed by the standard, and should actually should call correctly within the hirearchy at that level (with some limitations)
C++ constructors: why is this virtual function call not safe?
http://www.parashift.com/c%2B%2B-faq-lite/calling-virtuals-from-ctors.html
However, there are many, many reasons not to do this.
The constructor for the derived class has not been called yet. Any access of any members of the derived class will yield undefined behavior.
There is a rule of thumb that you should keep constructors as simple and dumb as possible. This is due to the fact that error handling in constructors can be a giant pain due to destructor not being called and the only way to return a sensical error state is to throw an exception.
This will often break the dependency inversion principal, and may cross the line of demeter, and will usually introduce high coupling to the code.
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.
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
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.