order of destruction using virtual
Asked Answered
P

8

12

Can some one please help what the order of destruction is when I am using virtual functions. Does it start with the base class and then derived class?

Percolation answered 17/8, 2010 at 21:29 Comment(0)
F
14

Since I don't see how virtual function change any objects' destruction order, I assume you're referring to the order of destruction for base classes and data members in a virtual inheritance scenario.

Sub-objects are constructed

  1. base classes are constructed from most base to most derived;
  2. multiple base classes are constructed in the order of their declaration as base classes;
  3. virtual base classes are constructed before all others, amongst themselves adhering to the above two rules;
  4. data members are constructed before the enclosing object's constructor's body is executed, in order of their declaration.

Destruction is simply the opposite of construction, so you only need to memorize the above.

However, the above four rules are in that order because that makes sense, and if you understand why this order makes sense, you will not even have to memorize those four rules, but can infer them from your understanding (as I just did). So let's examine that order:

  • You might want to use whatever service the base class provide from a derived class' constructor. Of course, you cannot use a (base) class object before it's actually constructed. Therefore, when a derived class is constructed, the base class needs to be already constructed. (Incidentally, this also explains why the virtual function dispatching doesn't fully work from within constructors: When a sub-object is constructed, only the sub-objects of base classes are already constructed; the derived classes' sub-objects are not yet constructed. Therefore a call to a virtual function must not be dispatched to a derived class. As always, destructors are the same, just backwards.)
  • With multiple base classes being equal siblings, some order had to be picked arbitrarily. Ultimately, the order of declaration is the most simple one to use. Data members, which also are equal siblings, follow the same (more or less arbitrary) in-order-of-declaration rule.
  • Virtual base classes are strange beasts. Because there will always only be one sub-object of a virtual base class, there's that special rule which says it always needs to be constructed first, right from the most derived class' constructor. (Which is why virtual base classes work best as abstract base classes with no data and only default constructors.)
Fifield answered 17/8, 2010 at 21:43 Comment(2)
Actually I think he spoke about a virtual destructor.Alla
@Matthieu: It seems I was right. :) (Thanks for fixing the grammar!)Fifield
R
5

Assuming you have correctly declared your destructor as virtual.

Then destruction is done in the exact opposite order of construction.

In General this will be:

A) Start in the most derived class.
B) Repeat the following recursively.

1) Execute the destructor code.
2) Execute the destructor of each member (in reverse order of creation)
3) Execute the destructor of the parent class. (if more than one in reverse order of creation)

If you use virtual inheritance though then things are slightly different as the order of base class construction is not the same as normal. BUT The order of destruction is ALWAYS the reverse of the order of construction.

Revelatory answered 17/8, 2010 at 21:31 Comment(0)
B
1

The destruction order is the construction order backwards. I've recently made a small tool to display the construction order for any hierarchy. Look here:

In the diagrams, the nodes with the smaller numbers are constructed first and destructed last.

Benghazi answered 17/8, 2010 at 21:32 Comment(0)
N
1

Section 12.6.2/5:

Initialization shall proceed in the following order:

  • First, and only for the constructor of the most derived class as described below, virtual base classes shall be 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 class names in the derived class base-specifier-list.
  • Then, direct base classes shall be initialized in declaration order as they appear in the base-specifier-list (regardless of the order of the mem-initializers).
  • Then, nonstatic data members shall be initialized in the order they were declared in the class definition (again regardless of the order of the mem-initializers). — Finally, the body of the constructor is executed.

[Note: the declaration order is mandated to ensure that base and member subobjects are destroyed in the reverse order of initialization. ]

Nettles answered 18/8, 2010 at 9:19 Comment(0)
S
0

Virtual functions make no difference to the order of destruction, virtual base classes, on the other hand, do.

Without virtual base classes, derived classes are always destroyed before their base classes; this is the reverse order in which they are constructed.

For the most derived class, virtual base classes are constructed first, before other base classes and before the most derived class itself. Destruction happens in the reverse order. This means that a virtual base may be destroyed after a class that derives virtually from it, if that class is not the most derived class being destroyed. This can never happen for direct base classes.

Spiffy answered 17/8, 2010 at 21:31 Comment(3)
So avoid impure MI when in a sane environment? Gotcha :)Benadryl
@Merlyn Morgan-Graham: What do you mean by "impure MI"?Spiffy
By impure, I mean anything where virtual inheritance would matter. Any multiple inheritance on base classes that aren't purely abstract. I thought having to pre-plan multiple inheritance with the "virtual" keyword on base classes was nasty enough. Finding out the destructor/constructor order makes it way worse :)Benadryl
T
0

It is the opposite way as the constructors. So derived first.

Trumantrumann answered 17/8, 2010 at 21:31 Comment(0)
K
0

Order of destructions if from the bottom up. (from derived to base)

Short answer: the exact opposite of the constructor order.

Long answer: suppose the "most derived" class is D, meaning the actual object that was originally created was of class D, and that D inherits multiply (and non-virtually) from B1 and B2. The sub-object corresponding to most-derived class D runs first, followed by the dtors for its non-virtual base classes in reverse declaration-order. Thus the destructor order will be D, B2, B1. This rule is applied recursively; for example, if B1 inherits from B1a and B1b, and B2 inherits from B2a and B2b, the final order is D, B2, B2b, B2a, B1, B1b, B1a.

See the c++ faq section 25

Kana answered 17/8, 2010 at 21:32 Comment(0)
M
0

First the derived, then the base. No difference wrt the non-virtual cases.

Additional note. When you have inheritance and virtual methods, you have to declare destructors as virtual, otherwise you can have undefined behavior at deletion.

Example, suppose Derived is derived from Base, and you allocate Derived with the following line:

Base *o = new Derived();
delete(o);

If this case occurs in your code, and Base has no virtual destructor, the resulting behavior is undefined. Typically, only the destructor of Base will be called. The destructor of Derived will not be called, because you are calling delete on a Base pointer. However, the program might crash instead. Once you are in the realm of undefined behavior, all bets are off and your running code is doomed. To prevent chaos the Base destructor must be virtual.

Misdemeanant answered 17/8, 2010 at 21:33 Comment(1)
Not strictly accurate. If Base has no virtual destructor then the behaviour is undefined. It may or may not be the case that either Base or Derived destructors are called or the program might just crash.Spiffy

© 2022 - 2024 — McMap. All rights reserved.