When an object goes out of scope or is deleted, the sequence of events in its complete destruction is as follows:
1.The class's destructor is called, and the body of the destructor function is executed.
2.Destructors for nonstatic member objects are called in the reverse order in which they appear in the class declaration. The optional member initialization list used in construction of these members does not affect the order of construction or destruction. (For more information about initializing members, see “Initializing Bases and Members”.)
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.
When calling destructors for nonvirtual base classes, the destructors are called in the reverse order in which the base class names are declared. Consider the following class declaration:
class MultInherit : public Base1, public Base2
...
In the preceding example, the destructor for Base2 is called before the destructor for Base1.
Destructors for virtual base classes are called in the reverse order of their appearance in a directed acyclic graph (depth-first, left-to-right, postorder traversal). Figure 11.1 depicts an inheritance graph.
The following lists the class heads for the classes shown in Figure 11.1.
class A
class B
class C : virtual public A, virtual public B
class D : virtual public A, virtual public B
class E : public C, public D, virtual public B
To determine the order of destruction of the virtual base classes of an object of type E, the compiler builds a list by applying the following algorithm:
1.Traverse the graph left, starting at the deepest point in the graph (in this case, E).
2.Perform leftward traversals until all nodes have been visited. Note the name of the current node.
3.Revisit the previous node (down and to the right) to find out if the node being remembered is a virtual base class.
4.If the remembered node is a virtual base class, scan the list to see if it has already been entered. If it is not a virtual base class, ignore it.
5.If the remembered node is not yet in the list, add it to the bottom of the list.
6.Traverse the graph up and along the next path to the right.
7.Go to step 2.
8.When the last upward path is exhausted, note the name of the current node.
9.Go to step 3.
10.Continue this process until the bottom node is again the current node.
So, for class E, the order of destruction is:
1.The nonvirtual base class E.
2.The nonvirtual base class D.
3.The nonvirtual base class C.
4.The virtual base class B.
5.The virtual base class A.
This process produces an ordered list of unique entries. No class name appears twice. Once the list is constructed, it is walked in reverse order, and the destructor for each of the classes in the list from the last to the first are called.
The order of construction or destruction is primarily important when constructors or destructors in one class rely on the other component being created first or persisting longer—for example, if the destructor for A (in the graph in Figure 11.1) relied on B still being present when its code executed, or vice versa.
Such interdependencies between classes in an inheritance graph are inherently dangerous because classes derived later can alter which is the leftmost path, thereby changing the order of construction and destruction.