I am writing this blog post largely in response to John’s blog post: Public Virtual Methods: A Bad Idea. John and I work closely, and have for as long as I have been at Spatial. I like working with him because,
John has always been good about thinking over ideas together, so I don’t think this particular post should cause me too much trouble. Before I start my main argument, I should stipulate that in the case where you use inheritance to make some of the implementation of the derived class John’s argument is perfectly correct.
Please examine the following header file snippet:
Is this in any way bad style? Does the interface presented have the problem of trying to serve two purposes?
A purely abstract class (i.e., all virtual pure methods, except destructor which is impure but virtual) merely defines method names and signatures; it just defines syntax for service providers and clients to mediate provision of services. COM utilizes this pattern extensively to good effect. Also, CGM operators follow this pattern: in CGM, clients of the library are not typically expected to derive operators merely make them and use them. Arguably, this programming standard is better than many others one might encounter.
Inheritance makes C++ much more convenient for writing maintainable software then, for example, C or Fortran. But inheritance in general may be more trouble than it is worth. For example, the Gang of Four book (link to Wikipedia http://en.wikipedia.org/wiki/Design_Patterns) argues to "Favor object composition over class inheritance". Even using public inheritance to implement functionality in derived classes runs some risk of coupling between the base class and the derived class. If C++ where modified to allow classes with public and private access, and forbid all forms of inheritance other than inheritance from interfaces (i.e., abstract base classes with only pure virtual methods), I think it would be just as useful as it is now (but a lot more verbose).
The main argument for this point consists of a simple refactoring. Suppose we have an abstract base class with private virtual methods:
We can always write code that does the same thing without inheriting from the implementation as follows:
In the implementation of BaseClass you merely call pd->CustomizableStep1(/*…*/) rather than ABaseClass::CustomizableStep1(/*…*/).
There are a couple of subtleties here:
Click to Enlarge Image
What do you think?
These Stories on CGM Modeler
ACIS, 3DScript and SAT are registered trademarks of Spatial Corp.
No Comments Yet
Let us know what you think