Is the order of destruction well defined in the case of multiple inheritance?
struct A
{
~A(){std::cout << "A\n";}
};
struct B
{
~B(){std::cout << "B\n";}
};
struct AB : public B, public A
{
~AB(){std::cout<<"AB\n";}
};
int main()
{
AB ab;
}
For the given code my compiler prints:
AB
B
A
But I use more complex constructs (including CWinApp
), I get different results. So is the order well-defined? And if so, what is the ordering rule?
To destroy means to obliterate a court record or file in such a way as to make it permanently irretrievable. A motion or order to expunge shall be treated as a motion or order to destroy. (4) Seal. To seal means to protect from examination by the public and unauthorized court personnel.
Destructors for virtual base classes are called in the reverse order of declaration.
Destructors are called in the order "most derived to most basal", and in reverse order of declaration. So ~AB is called first, then ~B , then ~A , because AB is the most derived class.
Which class destructor will be called first, when following code go out of scope? Explanation: The constructor that would have created at last, its destructor will be called first when the code goes out of scope. This will help the program to manage the resources more efficiently.
From [class.dtor]:
Bases and members are destroyed in the reverse order of the completion of their constructor (see 12.6.2).
The constructor ordering, from [class.base.init]:
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 [ ... ]
— 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).
For your example:
struct AB : public B, public A
The construction order is B
then A
then AB
. So the destruction order is AB
then A
thenB
.
The C++11 Standard makes this clear (S10.1), for multiple inheritance
The order of derivation is not significant except as specified by the semantics of initialization by constructor (12.6.2), cleanup (12.4), and storage layout (9.2, 11.1).
But you can guarantee that the destruction order is the reverse of the construction.
From the friendly manual (abbreviating #2 a bit):
- The class's destructor is called.
- Destructors for nonstatic members in reverse order of declaration.
- Destructors for nonvirtual base classes are called in the reverse order of declaration.
- Destructors for virtual base classes are called in the reverse order of declaration.
So your compiler emits code that destructs in the order AB, B, A.
[Edit 20150725: Barry's repeated comments eventually led me to notice that I had typoed "This is not" as "This is also". Of course, having typed it, I couldn't see it until I did. Meh. Thus, the one changed word in the following.]
This is not the order from isocpp.org's FAQ. That entry refers to the same question about constructor ordering, where the text "Note that the order B1 and then B2 (or B1a then B1b) is determined by the order that the base classes appear in the declaration of the class, not in the order that the initializer appears in the derived class’s initialization list." appears, highlighting that declaration order is the relevant order.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With