Understanding the order of constructors and destructors

Share the Article

When a class design is very complex, then the order of call of constructors and destructors becomes very important. For instance, assume that there is a design where there are base classes, derived classes, multiple inheritance and member objects in these classes. Now, the calling constructors and destructors shall follow a specific order as shown below:

Constructor order

  1. Base class member objects (in order of occurrence inside  base class)
  2. Base class constructors (in order of specification for multiple inheritance)
  3. Derived class member objects (in order of occurrence inside derived class)
  4. Derived class constructor

Destructor order

  • This will be follow exactly opposite order followed by the constructor
#include <iostream> using namespace std; class Base1member { public: Base1member() { cout << "Base1member()" << endl; } ~Base1member(){ cout << "~Base1member()" << endl; } }; class Base2member { public: Base2member() { cout << "Base2member()" << endl; } ~Base2member(){ cout << "~Base2member()" << endl; } }; class Derivedmember { public: Derivedmember() { cout << "Derivedmember()" << endl; } ~Derivedmember(){ cout << "~Derivedmember()" << endl; } }; class Base1 { Base1member b1; public: Base1() { cout << "Base1()" << endl; } ~Base1(){ cout << "~Base1()" << endl; } }; class Base2 { Base2member b2; public: Base2() { cout << "Base2()" << endl; } ~Base2(){ cout << "~Base2()" << endl; } }; class Derived : public Base2, public Base1 { Derivedmember d; public: Derived() { cout << "Derived()" << endl; } ~Derived(){ cout << "~Derived()" << endl; } }; int main() { Derived dobj; }

The output is:

Base2member() Base2() Base1member() Base1() Derivedmember() Derived() ~Derived() ~Derivedmember() ~Base1() ~Base1member() ~Base2() ~Base2member()

No relation to constructor initializer list :

It’s also interesting to note that the order of constructor calls for member objects is completely unrelated to the order of the calls in the constructor initializer list. The order is determined by only one order which is how the member objects are declared in the class.

This is because, if the C++ compiler allows to change order of constructor calls due to its constructor initializer list then it will have side-effects. For example, a class may end up having two different constructor call sequences when such a class contains two different constructors.

However, then the destructor cannot know that which destructor order will be considered for properly destructing the objects. This will end up in a dependency problem.

Example of 2 constructors having different initializer list order:

there are 2 constructors in class MainFunda and both are specifying different order of initialization of member objects in constructor initializer lists. However, we will see that compiler will completely ignore such lists and follow the logical order explained above:

#include <iostream> //main header using namespace std;//for namespace class member1 { public: member1() { cout << "member1()" << endl; } ~member1(){ cout << "~member1()" << endl; } }; class member2 { public: member2() { cout << "member2()" << endl; } ~member2(){ cout << "~member2()" << endl; } }; class MainFunda { member1 m1; member2 m2; public: MainFunda() : m2(), m1() //Initialization Order#1 { cout << "MainFunda()" << endl; } MainFunda(int x) : m1(), m2() //Initialization Order#2 { cout << "MainFunda(int)" << endl; } ~MainFunda() { cout << "~MainFunda()" << endl; } }; int main() { MainFunda a1; MainFunda a2(8); }

The output shows same order of construction of member1 & member2 in both:

member1() member2() MainFunda() member1() member2() MainFunda(int) ~MainFunda() ~member2() ~member1() ~MainFunda() ~member2() ~member1()

Main Funda: The order of calls of constructors and destructors are exactly opposite to each other

Related Topics:

Parametrized constructor
Virtual Destructor & Pure Virtual Destructor
Smart Pointers: unique_ptr<T>
Diamond problem – Overhead of virtual base
Multiple Inheritance has multiple this pointers
Understanding multiple inheritance & virtual base classes
Understanding the copy constructor
What is an explicit constructor ?
Smart Pointers: shared_ptr <T> 
What is move constructor ?
What happens when exception thrown from a constructor?
Why a destructor should never throw exception?
Compiler Generated Destructor is always non-virtual
Which member functions are generated by compiler in class?
Understanding array version of new[] & delete[]

Share the Article

Leave a Reply

Your email address will not be published. Required fields are marked *