TITLE: pure virtual destructors - a summary (Newsgroups: comp.lang.c++,comp.lang.c++.moderated, 4 Dec 98) HYSLOP: jim.hyslop@leitch.com This article is a summary of the discussions in the various threads in comp.lang.c++ and comp.lang.c++.moderated concerning pure virtual destructors. Given the fact that the threads are so long and so many good points were made, this summary cannot obviously cover the topic in detail. The full threads can be viewed by visiting DejaNews (http://www.dejanews.com), clicking on "Power Search", and entering the subject "(pure and virtual and destructor) or virtula" (without the quotes, of course) and selecting the forum "comp.lang.c++" (DejaNews will automatically pick up .moderated) ------------- "So, what is the point of a pure virtual destructor?" A seemingly innocent question, which should have a straightforward answer - but one that has generated a week and a half's worth of interesting discussion and a thread close to 60 messages long (as of Dec. 4). We all know the uses of virtual functions, and we also know the uses of pure virtual functions. But, given the fact that a destructor must always be implemented, and given the fact that a pure specifier implies that (as [SAILORS] put it) "implementation is optional", it does not seem to make sense to allow a destructor to be pure. There are four possible scenarios for base class destructors: - Non-virtual destructor. - Virtual (not pure) destructor - Pure virtual destructor, no implementation - Pure virtual destructor, with an implementation The pros and cons of each of the four scenarios are: Non-virtual destructor: This would, at first, seem to be a bad idea - if the class is destroyed polymorphically, then the derived class' dtor will never be called. However, one phrase that popped up several times in the discussion was "With C++, you don't pay for what you don't need." [BECKER] pointed out that you might have a mixin class - with such a class, you do not want to destroy the class with a pointer to the mixin, so the mixin's dtor should not be virtual (this makes it plain wrong to use the mixin pointer). [GLASSBOROW] pointed out, however, that since you don't destroy the class via a pointer to the mixin anyway, it's a not as critical if the mixin's dtor is virtual. [THOMAS] reminded us that calls routed through virtual tables being more expensive than calls not routed through virtual tables, but [LEICHTER] pointed out that, for a dtor, there should be at most one virtual lookup - when a derived class invokes the base class dtor, the compiler should be able to statically resolve the call. As pointed out by several people, if you do make the dtor non-virtual, you must be absolutely sure the derived classes will never be destroyed polymorphically. Virtual (not pure) destructor: We are all aware of the reasons for this - if the class is destroyed polymorphically, the derived class dtor will not be called. This is a no-brainer and no further discussion is required. (As a side note, several people wrote that they used pure functions to force all derived classes to implement the functions - the response to which was, of course, that only the final class has to implement them; intermediate base classes can leave the pure functions un-implemented.) Pure-virtual, dtor not implemented: I did not see any discussion on this scenario, probably because it is not a legal scenario anyway - the destructor must be implemented or you'll get a runtime error. Pure-virtual, dtor implemented: "So, what is the point of a pure virtual destructor?" - the crux of the matter. What this boils down to is, why allow a dtor to be pure, given that you must implement it? The most common answer (apart from the obvious "To make it abstract - DUH") was [MEYERS] point - a class where none of the virtual functions are realistically required to be overridden by all derived classes. The challenge, as stated by [HYSLOP], was to provide a realistic example of such a heirarchy. The best example given was [MENZL]'s suggestion of the [GoF] State pattern, where the base, abstract class provides default functionality for all functions, and various functions are expected to be overridden by the derived classes (individual states). To summarize the summary :-): In general, base class destructors should be non-pure virtual functions if the base class has any virtual functions. If your design can be sure that the derived classes will never be destroyed polymorphically, and if your program cannot handle one more pointer inside a vtable or the time required for one virtual lookup, then it is reasonable to make the destructor non-virtual. If you want your base class to be abstract, but none of your virtual member functions can be reasonable required to be pure, then make the dtor pure, but be sure to implement it! I hope I have provided an accurate summary of the salient points of the discussion. Print references: [MEYERS] - Scott Meyers, "Effective C++" [GoF] Gamma, Helm et al. "Design Patterns" Usenet discussion references: [BECKER] - Pete Becker petebecker@acm.org [GLASSBOROW] - Francis Glasborow francis@robinton.demon.co.uk [HYSLOP] Jim Hyslop jim.hyslop@leitch.com [LEICHTER] Jerry Leichter leichter@smarts.com [MENZL] - Gerhard Menzl gerhard.menzl@sea.ericsson.se [SAILORS] - Skip Sailors rsailors@wyoming.com [SHIVA] - J Shiva jshiva@bigfoot.com [THOMAS] - Biju Thomas bijuthom@ibm.net Many others contributed to the conversation - I have only listed the people I referred to above.