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 delete
d 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.