15.10 VIRTUAL DESTRUCTORS IN C


15.10 VIRTUAL DESTRUCTORS IN C++

The previous section showed three programs, OverrideReturnRestrict.cc, PrivateVirtual.cc and OverrideExceptionRestrict.cc, in which we declared the base class destructors to be virtual. Each of these programs would have a memory leak if the base class destructor was not declared virtual. The main in these programs invokes delete on a base-class pointer that is actually pointing to a derived-class object. If the base class destructor is not virtual, invoking delete on a base-class pointer will only delete the base-class subobject inside the derived class object. What's interesting here is that, in and of themselves, the base classes in each of the three programs do not need programmer–supplied destructors since the default meaning of object destruction for these simple classes would suffice. But when we derive classes from these base classes and we want object destruction to occur polymorphically on base-class pointers, we have to explicitly supply the base classes with destructors even though they have empty bodies.

For another example, consider the case of a vector of pointers to the base-class type, where some of the pointers are actually pointing to objects of a derived-class type. Let's say that you now set up a loop in which you invoke the delete operator on each of the pointers, with the hope that the destructor invoked for each object would be the one defined specifically for it. In other words, you'd want the destructor invocation to behave polymorphically. This will only happen if you declare the destructor to be virtual in the base class.

As a simple demonstration of a virtual destructor in action, consider the following program in which the base-class X extends into the derived-class Y, which in turn extends into a further derived-class Z. The base-class X is provided with a virtual destructor, declared in line (A) and defined in line (B). As we will demonstrate, this declaration causes the destructor invocations in the 3–layer class hierarchy to behave polymorphically.

 
//VirtualDestructor.cc #include <iostream> using namespace std; class X { // BASE public: virtual ~X(); //(A) }; X::~X(){ cout << "X's destructor" << endl; } //(B) class Y : public X { // DERIVED public: ~Y() { cout << "Y's destructor" << endl; } }; class Z : public Y { // DERIVED public: ~Z() { cout << "Z's destructor" << endl; } }; int main() { X* p = new Z(); //(C) delete p; //(D) return o; }

In main of the above program, we construct an object of type Z and assign it to a base-class pointer of type X* in line (C). When we invoke delete on this pointer in line (D), we get the following output from the program:

      Z's destructor      Y's destructor      X's destructor 

implying that the runtime correctly identified the true identity of the object—it being of type Z—pointed to by p and thus invoked the destructor for Z. The Z destructor called Y's destructor to destroy the Y slice of the Z object. And, Y's destructor called the X's destructor for destroying the X slice inside the Y subobject. That accounts for the 3-line output of the program. The program would display the same correct behavior even if replace the statements in lines (C) and (D) of main by

      Y* q = new Z();                                 //(E)      delete q;                                       //(F) 

Knowing that object destruction is to behave polymorphically in all classes derived from X, the runtime will seek out the true identity of the object pointed to by q and then invoke the destructor for that object. So, as before, Z's destructor will be invoked again and the same 3-line ouput produced.

If the keyword virtual was dropped in line (A) of the program, the output of the VirtualDestructor.cc program would be

    X's destructor 

implying that only the X slice of the Z object of line (C) was getting destroyed. If the statements in lines (C) and (D) are replaced by those in lines (E) and (F), then without the virtual destructor, only the Y slice of the Z object of line (E) will be destroyed, producing the output

     Y's destructor     X's destructor 




Programming With Objects[c] A Comparative Presentation of Object-Oriented Programming With C++ and Java
Programming with Objects: A Comparative Presentation of Object Oriented Programming with C++ and Java
ISBN: 0471268526
EAN: 2147483647
Year: 2005
Pages: 273
Authors: Avinash Kak

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net