Destructor ordering in inheritance hierarchy - c++

If I have the following hierarchy:
Class F contains member objects of type (Class E and Class D, declared in that order)
Class F inherits the concrete class Class C
Class C inherits the abstract/pure virtual class Class B
Class B inherits the concrete class class A
If the destructor for object of type Class F is called, the following happen in the below order:
Class F (the most derived) destructor is called and finishes
Class D (member object 2) destructor is called and finishes
Class E (member object 1) destructor is called and finishes
Class C (base of F) destructor is called and finishes
Class A (base of B, which is base of C) destructor is called and finishes
Class B (virtual, base of C) destructor is called and finishes
is this correct? So basically towards the end C inherits virtual B and virtual B inherits A, but C gets destroyed, then A, then virtual B?
EDIT: C++ FAQs says:
"Virtual base classes are special- their destructors are called at the
end of the most derived class's constructor"
which is what I am trying to understand?

Destructors execute in reverse order of constructors. That is pretty much all you need to know.
UPDATE: It holds even for virtual bases. You just have to realize that virtual bases are constructed before any other base class.

Maybe it's easiest to express the order of destructor calls as an algorithm.
Destroy
Do whatever the programmer wrote in the destructor's body: F::~F() { do_this; do_that; }
Destroy (call destructors for) members
Destroy (call destructors for) non-virtual base classes
Destroy (call destructors for) virtual base classes
This algorithm is performed by the language (or compiler), so the programmer can control only the first step.
Note: each of the further steps is recursive.
The order of destructor calls is the reverse order of constructor calls (it's good to know because the construction order is intuitive). The order of destruction of virtual bases is specified as
depth-first left-to-right traversal of the graph of base classes
Fortunately, you don't need this because you only have one.

Related

Do children classes inherit parent's Destructors if not done manually?

If given a parent class A that contains a defined Destructor, will B-it's child- execute it when creating a B object? even if I did not create manually nor inherit the A's Destructor in the B class?
I expect that it will since I saw it in a video tutorial of c++ but do not understand why? Because the Constructor was manually inherited!
The compiler always implements a destructor for your class, if you haven't declared one. The compiler also generates code that calls base class destructors.
In other words, base class destructors are not inherited but get called from after your derived class destructor.
See Destructor:
Destruction sequence
For both user-defined or implicitly-defined destructors, after the body of the destructor is executed, the compiler calls the destructors for all non-static non-variant members of the class, in reverse order of declaration, then it calls the destructors of all direct non-virtual base classes in reverse order of construction (which in turn call the destructors of their members and their base classes, etc), and then, if this object is of most-derived class, it calls the destructors of all virtual bases.
Even when the destructor is called directly (e.g. obj.~Foo();), the return statement in ~Foo() does not return control to the caller immediately: it calls all those member and base destructors first.
The child class inherits the data members and member function of parent class but private members remain inaccesible in child class.Only Public member function and data members are accecible in child class.In Inheritance constructor or destructor is not inherited by child class but in the child class constructor and destructor there is an explicit call to base class constructor and destructor.
whenever we create an object of child class ,first constructoe of base class will be invoked then constructor of derived class is called.while if the object of child class is destroyed the destructor of child class will be invoked first and then destructor of parent class will be called.

Double inheritance with non-virtual destirutor (Y-shaped)

I have Y-shaped class hierarchy: class C inherits from A and B, and class D inherits from C. A and B have virtual destructors and C's destructor is not virtual. I know that if there is no double inheritance (say no B) ~C() will be virtual. My question is does double inheritance affects it?
class A { virtual ~A(); ...};
class B { virtual ~B(); ...};
class C : public A, public B { ~C(); ...};
class D : public C { virtual ~D(); ... };
I have to delete instances of class D through a pointer to C.
C* c = new D;
delete c;
I suspect that there are some corner cases where ~B() is not executed - is it possible? Can it depend upon level of optimizations? Should definition of to D present in .cc file where 'delete c' is called?
All destructors except ~B() are nops, class C is empty class: no data members, no functions, just a trivial constructor and an empty destructor. I wrote several test programs in all cases ~B() was executed, but I am sure I did not try all the possible combinations.
C destructor is implicitly virtual since at least one of its base destructor is virtual.
Thus because C destructor is virtual and you delete through a pointer to C, D destructor would be called.
If neither A or B destructor would be virtual, then it would be undefined behavior to delete a D object but this is not the case here.
If a class C derive from class(es), then it knows how to destroy its base classes. Thus B destructor would always be called (assuming that you delete either the final object or from a level where the destructor is virtual either explicitly or implicitly.
In practice, even in the undefined case (only D destructor is virtual and object is deleted through C pointer), B destructor would probably have been called but D part would not have been properly destroyed. But since, it is undefined, you cannot rely on that.
C's destructor is not virtual.
Yes it is. It has base(s) with a virtual destructor(s), so the destructor of C is implicitly virtual. Whether the destructor is declared virtual explicitly or not is irrelevant. Same goes for destructor of D.
I have to delete instances of class D through a pointer to C.
I suspect that there are some corner cases where ~B() is not executed - is it possible?
As long as C's destructor is virtual, there is no problem. If C's destructor wasn't virtual, then deleting a dervied object through a pointer to C would have undefined behaviour.
As far as I know, destructor chaining has nothing to do with virtual destructor. As long as destructor of certain class is invoked, it will automatically invoke the base class desctructors for you.
What Virtual-ness of Desctructor come into picture is when you are deleting a derived class instance through a pointer of base class.
In your above example, assuming ~C is not virtual (i.e. you are not declaring virtual for any destructor), and if you are deleting a D instance through a C*, desctructor of D could have been missed, and compiler is going to call ~C for you instead. As mentioned above, calling ~C is going to cause all base class destrcutors (~A & ~B) to be called automatically.
However, given you have already declared destructor to be virtual in base class (A etc), virtual-ness will propagate to all derived classes' destructor. Which means, even you have not declared ~C as virtual, it is actually virtual.

Understanding virtual destructors

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

Are multiple-inherited constructors called multiple times?

Are multiple-inherited constructors called multiple times? And in what order are constructors called? Does this depend on the order in the inheritance list?
Here is an example (it's only for making the situation clear, no real-life example).
class Base {};
class DerivedBaseOne : public Base {};
class DerivedBaseTwo : public Base {};
class Derived : public DerivedBaseTwo, public DerivedBaseOne
{};
//somewhere in the code, is Base() called two times here?
Derived * foo = new Derived();
Is the Base() constructor called twice? And in what order are the constructors called? Base first? Or DerivedBaseOne() or DerivedBaseTwo() first?
The order of constructor calls for your inheritance hierarchy will be:
Base()
DerivedBaseTwo()
Base()
DerivedBaseOne()
Derived()
The order is indeed well-defined and depends on the order in which you mention the derivation for base classes and the order in which you declare members in the class for members. (See the reference from the C++ Standard below.)
Does the Base() constructor get called twice?
YES
The Base() class constructor gets called here twice, because two classes DerivedBaseTwo() and DerivedBaseOne() derive from it, so the base class constructor gets called once for each of them. Your Derived class has two distinct Base subobjects through multiple paths (one through DerivedBaseOne() and the other though DerivedBaseTwo()).
The hierarchy of classes you have with multiple inheritance is unusual and it leads to a problem called the Diamond Shaped Inheritance Problem. To avoid this problem C++ introduces the concept of Virtual base class.
Reference:
C++03 Standard: 12.6.2/5, Initializing bases and members
Initialization shall proceed in the following order:
— First, and only for the constructor of the most derived class as described below, virtual base classes shall be initialized in the order they appear on a depth-first left-to-right traversal of the directed acyclic graph of base classes, where “left-to-right” is the order of appearance of the base class names in the derived class base-specifier-list.
— Then, direct base classes shall be initialized in declaration order as they appear in the base-specifier-list (regardless of the order of the mem-initializers).
— Then, nonstatic data members shall be initialized in the order they were declared in the class definition (again regardless of the order of the mem-initializers).
— Finally, the body of the constructor is executed.
The way you write it, Derived has two distinct subobjects of type Base, and each gets their own constructor called from the respective DerivedBaseXXX constructor of which it is the subobject. The order of calls follows the order of declaration.
By contrast, of you declare DerivedBaseXXX : virtual public Base, then there is only one Base subobject, and its constructor is called from the most derived object, i.e. from the Derived object.
(To explain in a bit more detail: A (possibly singly-inheriting) class is constructed by first 1) calling the base class's constructor, then 2) calling the constructors of all member objects in their order of declaration, and finally 3) executing the constructor function body. This applies recursively, and for multiple inheritance, you just replace (1) by calling all the base class's constructors in the order in which the inheritance was declared. Only virtual inheritance adds a genuine extra layer of complication here.)
This is answered in: http://www.parashift.com/c++-faq-lite/multiple-inheritance.html#faq-25.14
The very first constructors to be executed are the virtual base classes anywhere in the hierarchy. They are executed in the order they appear in a depth-first left-to-right traversal of the graph of base classes, where left to right refer to the order of appearance of base class names.
Since your multiple inheritance declaration lists DerivedBaseTwo first, its construction order will be executed before DerivedBaseOne's.
So in your Derived class, DerivedBaseTwo and its chain is created first, that is:
1 - Base then DerivedBaseTwo
And then DerivedBaseOne and its chain:
2 - Base then DerivedBaseOne
And then:
3 - Derived is created after everything else.
Also, with multiple inheritance be mindful of the Diamond Inheritance Problem

Does a base class's constructor and destructor get called with the derived ones?

I have a class called MyBase which has a constructor and destructor:
class MyBase
{
public:
MyBase(void);
~MyBase(void);
};
and I have a class called Banana, that extends MyBase like so:
class Banana:public MyBase
{
public:
Banana(void);
~Banana(void);
};
Does the implementation of the new constructor and destructor in Banana override the MyBase ones, or do they still exist, and get called say before or after the Banana constructor / destructor executes?
Thanks, and my apologies if my question seems silly.
A Base constructor will always be called before the derived constructor.
The Base destructor will be called after Dervided destructor.
You can specify on derived constructor which Base constructor you want, if not the default one will be executed.
If you define other constructors but not default and don't specify on Derived constructor which one to execute it'll try default which doesn't exist and will crash compilation.
The above happens because once you declare one constructor no default constructors are generated.
Constructors cannot be overriden. You can't declare a base class constructor in a derived class. A class constructor has to call a constructor in base class (if one is not explicitly stated, the default constructor is called) prior to anything else.
To be able to clean up the derived class correctly, you should declare the base class destructor as virtual:
virtual ~MyBase() { ... }
It should say
class Banana : public MyBase
{
public:
Banana(void);
~Banana(void);
};
The constructor of the derived class gets called after the constructor of the base class. The destructors get called in reversed order.
The constructors are called top down in the inheritance tree. This is so that the derived constructor can count on the base object being fully initialized before it tries to use any properties of the base.
Destructors are called in reverse order of the constructors, for the same reason - the derived classes depend on the base, but the base doesn't depend on the derived.
If there is any possibility of destroying the object through a pointer to a base class, you must declare all of the destructors virtual.
Constructors and destructors are special member functions. In general you will read everywhere that construction starts from the least derived type all the way in the hierarchy down to the most derived type. This is actually the order in which constructor execution completes, but not how construction is started.
Constructors initialization list execution order guarantees that while the most derived object's constructor will be the first constructor to start executing it will be the last constructor to complete
When you instantiate an object the most derived constructor that matches the construction call gets called first. The initialization list of the matched most derived constructor starts, and initialization lists have a fixed order: first the constructors of the base classes in order or appearance within the inheritance list get called. Then the member attribute constructors are called in the order in which they appear in the class declaration (not the order in which they appear in the initialization list). After the whole initialization list (at each level) completes, the constructor body block is executed, after which the constructor call completes.
All base destructors will be called in reverse order of construction after the most derived destructor has completed execution. Destruction happens in exact reverse order of construction.
Destructors are special in a different way: they cannot be overriden. When you call the most derived destructor of a class, it will complete the execution of the destructor body, after which all member attribute destructors will be called in reverse order of creation. After the most derived destructor has completed and so have done the member destructors of the most derived object, the destructor of its most direct bases start in reverse order of construction, the destructor bodies will execute, then the member attributes destructors and so on... At the end all constructed elements will be destroyed.
Destructors for polymorphic classes should be virtual
The destruction description above starts with the call to the most derived destructor. This can be achieved by calling delete on a pointer to the most derived type, when an auto object goes out of scope or when the object is deleted through a base class whose destructor is virtual.
If you forget to add the destructor keyword in the base class and you try to delete a derived object through a pointer to the base you will call the base destructor directly, and that implies that all sub objects below the pointer type in the hierarchy will not be properly destroyed. All inheritance hierarchies in which you will delete objects through pointers to a base type must have virtual destructors. As a general rule of thumb, if you already have any virtual method, the cost of making the destructor virtual is negligible and is a safe net. Many coding guides enforce that destructors in inheritance hierarchies must be virtual. Some go as far as requesting all destructors to be virtual, This has the intention of avoiding possible resource leaks at the cost of adding a vtable for all types and an vtable pointer for all objects.
You are missing the type of inheritance:
Change
class Banana:MyBase
To:
class Banana: public MyBase
As for
does the implementation of the new
constructor and destructor in Banana
override the MyBase ones, or do they
still exist, and get called say before
or after the Banana constructor /
destructor executes?
The order of inherited executes from bottom to top, that means that MyBase will be called first, then Banana. If you had another subclass, it would be called last.
Take this example:
class RottenBanana : public Banana
The inheritance chain is now RottenBanana -> Banana -> MyBase
The constructors of this class will be called starting at MyBase, then Banana and then calling RottenBanana.
If you instantiate an EEGModeRGB object (which has tri-color led's attached) - then immediately delete it you'd see the colors Blue, Green, Yellow, and Red, for one second each - in that order.
class EEGMode {
public:
EEGMode() { setAllPixelsToColor(BLUE); delay(1000); }
virtual ~EEGMode() { setAllPixelsToColor(RED); delay(1000); }
};
class EEGModeRGB : public EEGMode {
public:
EEGModeRGB() { setAllPixelsToColor(GREEN); delay(1000); }
virtual ~EEGModeRGB() { setAllPixelsToColor(YELLOW); delay(1000); }
};