Order of calling constructors/destructors in inheritance
- Construction always starts with the base
class
. If there are multiple baseclass
es then, construction starts with the left most base. (side note: If there is avirtual
inheritance then it's given higher preference). - Then the member fields are constructed. They are initialized in the
order they are declared - Finally, the
class
itself is constructed - The order of the destructor is exactly the reverse
Irrespective of the initializer list, the call order will be like this:
- Base
class A
's constructor class B
's field nameda
(of typeclass A
) will be constructed- Derived
class B
's constructor
What is the order in which the destructors and the constructors are called in C++
The order is:
- Base constructor
- Derived constructor
- Derived destructor
- Base destructor
Example:
class B
{
public:
B()
{
cout<<"Construct B"<<endl;
}
virtual ~B()
{
cout<<"Destruct B"<<endl;
}
};
class D : public B
{
public:
D()
{
cout<<"Construct D"<<endl;
}
virtual ~D()
{
cout<<"Destruct D"<<endl;
}
};
int main(int argc, char **argv)
{
D d;
return 0;
}
Output of example:
Construct B
Construct D
Destruct D
Destruct B
Multiple levels of inheritance works like a stack:
If you consider pushing an item onto the stack as construction, and taking it off as destruction, then you can look at multiple levels of inheritance like a stack.
This works for any number of levels.
Example D2 derives from D derives from B.
Push B on the stack, push D on the stack, push D2 on the stack. So the construction order is B, D, D2. Then to find out destruction order start popping. D2, D, B
More complicated examples:
For more complicated examples, please see the link provided by @JaredPar
Change the order of constructors in inheritance
Your constant B::CONSTANT_B
can be static
, since it does not depend on a constructor argument.
static
s are initialised before your class objects are constructed (unless those are static
too!).
struct B : A
{
static const int CONSTANT_B = 3;
B() : A(CONSTANT_B)
{
write();
}
};
If B::CONSTANT_B
itself took its value from a constructor argument, you'd probably have to name that argument twice in the ctor-member-initialiser. There are no trivial workarounds for that as far as I can imagine.
struct B : A
{
const int CONSTANT_B;
B(const int constant)
: A(constant)
, CONSTANT_B(constant)
{
write();
}
};
C++ Constructor/Destructor inheritance
Terminology, terminology...
OK, what do we mean by "Foo is inherited"? We mean that if objects of class A
have Foo
in its interface, then objects of class B
which is a subclass of A
also have Foo
in its interface.
Constructors aren't a part of objects' interface. They belong directly to classes. Classes
A
andB
may provide completely different sets of constructors. No "being inherited" here.(Implementation detail: each B's constructors calls some A's constructor.)
Destructors indeed are a part of each object's interface, since the object's user is responsible for calling them (i.e. directly with
delete
or indirectly by letting an object out of scope). Each object has exactly one destructor: its own destructor, which might optionally be a virtual one. It is always its own, and it's not inherited.(Implementation detail: B's destructor calls A's destructor.)
So: there's a connection between base and derived constructors and destructors, but it's not like "they're inherited".
I hope this answers what you have in mind.
In what order will base classes be destroyed?
There are rules (C++11 §12.4):
After executing the body of the destructor and destroying any automatic objects allocated within the body, a destructor for class X calls the destructors for X’s direct non-variant non-static data members, the destructors for X’s direct base classes and, if X is the type of the most derived class (12.6.2), its destructor calls the destructors for X’s virtual base classes. All destructors are called as if they were referenced with a qualified name, that is, ignoring any possible virtual overriding destructors in more derived classes. Bases and members are destroyed in the reverse order of the completion of their constructor (see 12.6.2). A return statement (6.6.3) in a destructor might not directly return to the caller; before transferring control to the caller, the destructors for the members and bases are called. Destructors for elements of an array are called in reverse order of their construction (see 12.6).
The construction order is (§12.6.2/10):
In a non-delegating constructor, initialization proceeds in the following order:
— First, and only for the constructor of the most derived class (1.8), virtual base classes are 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 classes in the derived class base-specifier-list.
— Then, direct base classes are initialized in declaration order as they appear in the base-specifier-list (regardless of the order of the mem-initializers).
— Then, non-static data members are initialized in the order they were declared in the class definition (again regardless of the order of the mem-initializers).
— Finally, the compound-statement of the constructor body is executed.[ Note: The declaration order is mandated to ensure that base and member subobjects are destroyed in the
reverse order of initialization. — end note ]
So in simple cases, base constructors are called in the order in which the classes are listed in the declaration, and destructors run in reverse of that order.
Call of the destructors in multilevel inheritance (c++)
Inheritance is a red herring here. It's not relevant.
y
and z
have automatic storage duration and are required, in this case, to stay in scope until the closing brace of the function.
And z
will be destructed before y
. (Automatic variables go out of scope in the reverse order in which they were created, all other things being equal.)
Destructor ordering in inheritance hierarchy
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.
Related Topics
How to Parse Space-Separated Floats in C++ Quickly
Best Way to Store Currency Values in C++
How to Forward Declare an Inner Class
Std::String to Float or Double
Checking Cin Input Stream Produces an Integer
How to Change Mode from C++98 Mode in Dev-C++ to a Mode That Supports C++0X (Range Based For)
How to Efficiently Perform Double/Int64 Conversions With Sse/Avx
How to Find Which Elements Are in the Bag, Using Knapsack Algorithm [And Not Only the Bag'S Value]
What Exactly Is a Reentrant Function
Check If a String Contains a String in C++
Difference Between String and Char[] Types in C++
Difference Between Angle Bracket ≪ ≫ and Double Quotes " " While Including Header Files in C++
Is There Any Overhead to Declaring a Variable Within a Loop - C++
What How to Use Instead of the Arrow Operator, '-≫'
Is the Safe-Bool Idiom Obsolete in C++11
What Is the Type of Lambda When Deduced With "Auto" in C++11