Object Destruction
Go Up to C++ and Delphi Class Models
Two mechanisms concerning object destruction work differently in C++ from the way they do in Delphi. These are:
- Destructors called because of exceptions thrown from constructors
- Virtual methods called from destructors
Delphi style classes combine the methods of these two languages. The issues are discussed below.
Exceptions Thrown from Constructors
Destructors are called differently in C++ than in Delphi if an exception is thrown during object construction. Take as an example, class C, derived from class B, which is derived from class A:
class A
{
// body
} ;
class B: public A
{
// body
} ;
class C: public B
{
// body
} ;
Consider the case where an exception is raised in the constructor of class B when constructing an instance of C. What results in C++, Object Pascal, and Delphi style classes is described here:
- In C++, first the destructors for all completely constructed object data members of B are called, then A’s destructor is called, then the destructors for all completely constructed data members of A are called. However, the destructors for B and C are not called.
- In Object Pascal, only the instantiated class destructor is called automatically. This is the destructor for C. As with constructors, it is entirely the programmer’s responsibility to call inherited in destructors. In this example, if we assume all of the destructors call inherited, then the destructors for C, B, and A are called in that order. Moreover, whether or not inherited was already called in B’s constructor before the exception occurred, A’s destructor is called because inherited was called in B’s destructor. Calling the destructor for A is independent of whether its constructor was actually called. More importantly, because it is common for constructors to call inherited immediately, the destructor for C is called whether or not the body of its constructor was completely executed.
- In Delphi style classes, the VCL, FireMonkey and RTL bases (implemented in Object Pascal) follow the Object Pascal method of calling destructors. The derived classes (implemented in C++) do not follow either language method exactly. What happens is that all the destructors are called; but the bodies of those that would not have been called, according to C++ language rules, are not entered.
Classes implemented in Delphi thereby provide an opportunity to process any cleanup code you write in the body of the destructor. This includes code that frees memory for sub-objects (data members that are objects) that are constructed before a constructor exception occurs. Be aware that, for Delphi style classes, the clean-up code may not be processed for the instantiated class or for its C++-implemented bases, even though the destructors are called.
Virtual Methods Called from Destructors
Virtual method dispatching in destructors follows the same pattern that it did for constructors. This means that for Delphi style classes, the derived class is destroyed first, but the runtime type of the object remains that of the derived class throughout subsequent calls to base class destructors. Therefore, if virtual methods are called in library base class destructors, you are potentially dispatching to a class that has already destroyed itself.