Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Order of destruction in the case of multiple inheritance

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?

like image 477
user1235183 Avatar asked Jul 20 '15 14:07

user1235183


People also ask

What is destruction order?

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.

What is the order of destructor?

Destructors for virtual base classes are called in the reverse order of declaration.

How destructors are called with multiple inheritance?

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 destructor is called first?

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.


3 Answers

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.

like image 172
Barry Avatar answered Oct 14 '22 02:10

Barry


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.

like image 43
Bathsheba Avatar answered Oct 14 '22 00:10

Bathsheba


From the friendly manual (abbreviating #2 a bit):

  1. The class's destructor is called.
  2. Destructors for nonstatic members in reverse order of declaration.
  3. Destructors for nonvirtual base classes are called in the reverse order of declaration.
  4. 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.

like image 1
Eric Towers Avatar answered Oct 14 '22 02:10

Eric Towers