I l@ve RuBoard Previous Section Next Section

1.3 Multiple Inheritance to the Rescue?

A TemporarySecretary class inherits both the Secretary and the Temporary classes.[1] TemporarySecretary has the features of both a secretary and a temporary employee, and possibly some more features of its own. This leads to the idea that multiple inheritance might help with handling the combinatorial explosion of design choices through a small number of cleverly chosen base classes. In such a setting, the user would build a multi-threaded, reference-counted smart pointer class by inheriting some BaseSmartPtr class and two classes: MultiThreaded and RefCounted. Any experienced class designer knows that such a naïve design does not work.

[1] This example is drawn from an old argument that Bjarne Stroustrup made in favor of multiple inheritance, in the first edition of The C++ Programming Language. At that time, multiple inheritance had not yet been introduced in C++.

Analyzing the reasons why multiple inheritance fails to allow the creation of flexible designs provides interesting ideas for reaching a sound solution. The problems with assembling separate features by using multiple inheritance are as follows:

  1. Mechanics. There is no boilerplate code to assemble the inherited components in a controlled manner. The only tool that combines BaseSmartPtr, MultiThreaded, and RefCounted is a language mechanism called multiple inheritance. The language applies simple superposition in combining the base classes and establishes a set of simple rules for accessing their members. This is unacceptable except for the simplest cases. Most of the time, you need to carefully orchestrate the workings of the inherited classes to obtain the desired behavior.

  2. Type information. The base classes do not have enough type information to carry out their tasks. For example, imagine you try to implement deep copy for your smart pointer class by deriving from a DeepCopy base class. What interface would DeepCopy have? It must create objects of a type it doesn't know yet.

  3. State manipulation. Various behavioral aspects implemented with base classes must manipulate the same state. This means that they must use virtual inheritance to inherit a base class that holds the state. This complicates the design and makes it more rigid because the premise was that user classes inherit library classes, not vice versa.

Although combinatorial in nature, multiple inheritance by itself cannot address the multiplicity of design choices.

    I l@ve RuBoard Previous Section Next Section