Destructors are called when one of the following events occurs:
An object allocated using the new operator is explicitly deallocated using the delete operator. When objects are deallocated using the delete operator, memory is freed for the "most derived object," or the object that is a complete object and not a subobject representing a base class. This "most-derived object" deallocation is guaranteed to work only with virtual destructors. Deallocation may fail in multiple-inheritance situations where the type information does not correspond to the underlying type of the actual object.
A local (automatic) object with block scope goes out of scope.
The lifetime of a temporary object ends.
A program ends and global or static objects exist.
The destructor is explicitly called using the destructor function's fully qualified name. (For more information, see Explicit Destructor Calls.)
The cases described in the preceding list ensure that all objects can be destroyed with user-defined methods.
If a base class or data member has an accessible destructor, and if a derived class does not declare a destructor, the compiler generates one. This compiler-generated destructor calls the base class destructor and the destructors for members of the derived type. Default destructors are public. (For more information about accessibility, see Access Specifiers for Base Classes.)
Destructors can freely call class member functions and access class member data. When a virtual function is called from a destructor, the function called is the function for the class currently being destroyed. (For more information, see Order of Destruction.)
There are two restrictions on the use of destructors. The first restriction is that you cannot take the address of a destructor. The second is that derived classes do not inherit their base class's destructors. Instead, as previously explained, they always override the base class's destructors.