You are here:

C++/virtual descructor

Advertisement


Question
Suppose you have a C++ base class and several classes that inherit from it. What might happen if you do not write a virtual destructor for the base class?  

Answer
The quick answer is that instances of derived types can be improperly destroyed if they are deleted through pointers to their base class. If such instances hold onto resources such as memory or file handles then these might not be released back to the system and are therefore lost (leaked).

However a virtual base class destructor can be trivial if there is nothing for it to do:

   class Base
   {
   public:

   // ...

       virtual ~Base() {}

   // ...

   };

The above virtual destructor is trivial, virtual and inline. There are issues with functions (destructors are just special functions) that are both virtual and inline. Making them virtual requires that they have an address at which they can be called so that polymorphism can work. However for inlined functions the compiler places the code within the function inline at the point where the call is made (more like a #define macro that has proper compiler checking). So the compiler will definitely ignore you inline choice (in C++ your choice to inline a function is only ever taken as a hint by the compiler), and create a real (out of line) function anyway to support polymorphic usage cases. However the compiler may choose to inline a virtual function in usage cases where it can determine exactly which function to call at compiler time.

The other option is not to define the destructor inline:

   class Base
   {
   public:

   // ...

       virtual ~Base();

   // ...

   };

Then elsewhere:

   Base::~Base()
   {
   }

See http://msdn.microsoft.com/msdnmag/issues/0600/c/ for more on this subject.

Getting back to the main topic, a classic example uses a widget types. Widget is a term used for GUI elements such as edit boxes, push buttons, list boxes and the like.

For this example I refer to two specific widget types: ListBox and Picture, both of which are derived from a general Widget base class.

For this example suppose that a dialog (or dialog box) is a collection of widgets (or it owns such a collection). The collection of widgets would probably contain pointers to instances of the specific widgets on the dialog stored as Widget pointers (Widget*). When the dialog is destroyed each Widget in the collection is also destroyed by having delete called on each of the Widget pointers.

If Widget did _not_ have a virtual destructor then only the Widget destructor Widget::~Widget will be called, which will only do the general base Widget cleanup. If the specific type of a particular Widget were say a ListBox then the objects used for the list data would not be deleted. If it were a Picture widget that displayed a bitmap on the dialog then the memory that made up the bitmap would not be released, which could potentially be a large amount of memory.

If Widget has a virtual destructor then when a Widget pointer is used to delete a Widget the specific type of Widget's destructor is called, Listbox::~ListBox if it refers to a ListBox widget or Picture::~Picture if it refers to a Picture widget, which gives the specific widgets the chance to properly clean up and release any resources they hold.

For background information see the C++ FAQ at http://www.parashift.com/c++-faq-lite/, specifically section 20, inheritance basics, section 11, destructors and section 9, inline functions. In fact you might like to read through the whole of the FAQ before posting further questions as it is likely that most of your questions will be answered by the FAQ!  

C++

All Answers


Answers by Expert:


Ask Experts

Volunteer


Ralph McArdell

Expertise

I am a software developer with more than 15 years C++ experience and over 25 years experience developing a wide variety of applications for Windows NT/2000/XP, UNIX, Linux and other platforms. I can help with basic to advanced C++, C (although I do not write just-C much if at all these days so maybe ask in the C section about purely C matters), software development and many platform specific and system development problems.

Experience

My career started in the mid 1980s working as a batch process operator for the now defunct Inner London Education Authority, working on Prime mini computers. I then moved into the role of Programmer / Analyst, also on the Primes, then into technical support and finally into the micro computing section, using a variety of 16 and 8 bit machines. Following the demise of the ILEA I worked for a small company, now gone, called Hodos. I worked on a part task train simulator using C and the Intel DVI (Digital Video Interactive) - the hardware based predecessor to Indeo. Other projects included a CGI based train simulator (different goals to the first), and various other projects in C and Visual Basic (er, version 1 that is). When Hodos went into receivership I went freelance and finally managed to start working in C++. I initially had contracts working on train simulators (surprise) and multimedia - I worked on many of the Dorling Kindersley CD-ROM titles and wrote the screensaver games for the Wallace and Gromit Cracking Animator CD. My more recent contracts have been more traditionally IT based, working predominately in C++ on MS Windows NT, 2000. XP, Linux and UN*X. These projects have had wide ranging additional skill sets including system analysis and design, databases and SQL in various guises, C#, client server and remoting, cross porting applications between platforms and various client development processes. I have an interest in the development of the C++ core language and libraries and try to keep up with at least some of the papers on the ISO C++ Standard Committee site at http://www.open-std.org/jtc1/sc22/wg21/.

Education/Credentials

©2016 About.com. All rights reserved.