Previous section   Next section

Imperfect C++ Practical Solutions for Real-Life Programming
By Matthew Wilson
Table of Contents
Chapter 16.  Keywords


16.6. final

When I had the original idea for this book, I wrote down a lot of my own opinions on the language, and I also solicited some from others. One of the popular ones suggested was C++'s lack of an equivalent to Java's final keyword. For those not familiar, it basically says, "nothing can inherit from me" when applied to a class.

This sounds great in theory, and would doubtless have saved many unwary souls from being caught out by the perils of nonvirtual overriding, as well as prevented those bad boys[3] who I've witnessed deriving from std::string in order to provide an implicit conversion operator. The advice is, roughly:

[3] You know who you are!

"If your class should be inherited from, it should define a virtual destructor, or should derive from a class with a virtual destructor. If it does not define, or inherit, a virtual destructor, it should not be inherited from."

The reason for this is primarily because if you use a type polymorphically, it is possible to cause it to be deleted via a pointer to a base type. Without the virtual destructor, the derived parts would be left un-uninitialized, leading to resource leaks and/or program logic failure. There's also the "arrays of inherited types" issue, which we looked at already in section 14.5.

I think that this viewpoint is too narrow and, dare I say it, a little dated. It only really caters for the two programming paradigms of Polymorphism and Abstract Data Types, which doesn't really cover the full gamut. The new, powerful and (rightly) popular paradigm of Generics requires a whole new way of looking at types. In particular, types can be discriminated and manipulated by characteristics that have little or nothing to do with the C++ object model [Lipp1996], which means that applying adaptive veneers (see Chapter 21) that inherit from their parameterising type can be an appropriate and effective way of increasing flexibility and compatibility, while leaving the object model unchanged.

So we should be content with the freedom to do what we choose (i.e., no final), as long as we take the responsibility for our choices. (Experience, in other words!)


      Previous section   Next section