Back to Item 41: Differentiate between inheritance and templates.
Continue to Item 43: Use multiple inheritance judiciously.

Item 42: Use private inheritance judiciously.

Item 35 demonstrates that C++ treats public inheritance as an isa relationship. It does this by showing that compilers, when given a hierarchy in which a class `Student` publicly inherits from a class `Person`, implicitly convert `Student`s to `Person`s when that is necessary for a function call to succeed. It's worth repeating a portion of that example using private inheritance instead of public inheritance:

    class Person { ... };

    class Student:                      // this time we use
      private Person { ... };           // private inheritance

    void dance(const Person& p);        // anyone can dance

    void study(const Student& s);       // only students study

    Person p;                           // p is a Person
    Student s;                          // s is a Student

    dance(p);                           // fine, p is a Person

    dance(s);                           // error! a Student isn't
                                        // a Person

Clearly, private inheritance doesn't mean isa. What does it mean then?

"Whoa!" you say. "Before we get to the meaning, let's cover the behavior. How does private inheritance behave?" Well, the first rule governing private inheritance you've just seen in action: in contrast to public inheritance, compilers will generally not convert a derived class object (such as `Student`) into a base class object (such as `Person`) if the inheritance relationship between the classes is private. That's why the call to `dance` fails for the object `s`. The second rule is that members inherited from a private base class become private members of the derived class, even if they were protected or public in the base class. So much for behavior.

That brings us to meaning. Private inheritance means is-implemented-in-terms-of. If you make a class `D` privately inherit from a class `B`, you do so because you are interested in taking advantage of some of the code that has already been written for class `B`, not because there is any conceptual relationship between objects of type `B` and objects of type `D`. As such, private inheritance is purely an implementation technique. Using the terms introduced in Item 36, private inheritance means that implementation only should be inherited; interface should be ignored. If `D` privately inherits from `B`, it means that `D` objects are implemented in terms of `B` objects, nothing more. Private inheritance means nothing during software design, only during software implementation.

The fact that private inheritance means is-implemented-in-terms-of is a little disturbing, because Item 40 points out that layering can mean the same thing. How are you supposed to choose between them? The answer is simple: use layering whenever you can, use private inheritance whenever you must. When must you? When protected members and/or virtual functions enter the picture — but more on that in a moment.

Item 41 shows a way to write a `Stack` template that generates classes holding objects of different types. You may wish to familiarize yourself with that Item now. Templates are one of the most useful features in C++, but once you start using them regularly, you'll discover that if you instantiate a template a dozen times, you are likely to instantiate the code for the template a dozen times. In the case of the `Stack` template, the code making up `Stack<int>`'s member functions will be completely separate from the code making up `Stack<double>`'s member functions. Sometimes this is unavoidable, but such code replication is likely to exist even if the template functions could in fact share code. There is a name for the resultant increase in object code size: template-induced code bloat. It is not a good thing.

For certain kinds of classes, you can use generic pointers to avoid it. The classes to which this approach is applicable store pointers instead of objects, and they are implemented by:

1. Creating a single class that stores `void*` pointers to objects.
2. Creating a set of additional classes whose only purpose is to enforce strong typing. These classes all use the generic class of step 1 for the actual work.

Here's an example using the non-template `Stack` class of Item 41, except here it stores generic pointers instead of objects:

    class GenericStack {
    public:
      GenericStack();
      ~GenericStack();

      void push(void *object);
      void * pop();

      bool empty() const;

    private:
      struct StackNode {
        void *data;                    // data at this node
        StackNode *next;               // next node in list

        StackNode(void *newData, StackNode *nextNode)
        : data(newData), next(nextNode) {}
      };

      StackNode *top;                          // top of stack

      GenericStack(const GenericStack& rhs);   // prevent copying and
      GenericStack&                            // assignment (see
        operator=(const GenericStack& rhs);    // Item 27)
    };

Because this class stores pointers instead of objects, it is possible that an object is pointed to by more than one stack (i.e., has been pushed onto multiple stacks). It is thus of critical importance that `pop` and the class destructor not delete the `data` pointer of any `StackNode` object they destroy, although they must continue to delete the `StackNode` object itself. After all, the `StackNode` objects are allocated inside the `GenericStack` class, so they must also be deallocated inside that class. As a result, the implementation of the `Stack` class in Item 41 suffices almost perfectly for the `GenericStack` class. The only changes you need to make involve substitutions of `void*` for `T`.

The `GenericStack` class by itself is of little utility — it's too easy to misuse. For example, a client could mistakenly push a pointer to a `Cat` object onto a stack meant to hold only pointers to `int`s, and compilers would merrily accept it. After all, a pointer's a pointer when it comes to `void*` parameters.

To regain the type safety to which you have become accustomed, you create interface classes to `GenericStack`, like this:

    class IntStack {                  // interface class for ints
    public:
      void push(int *intPtr) { s.push(intPtr); }
      int * pop() { return static_cast<int*>(s.pop()); }
      bool empty() const { return s.empty(); }

    private:
      GenericStack s;                 // implementation
    };

    class CatStack {                  // interface class for cats
    public:
      void push(Cat *catPtr) { s.push(catPtr); }
      Cat * pop() { return static_cast<Cat*>(s.pop()); }
      bool empty() const { return s.empty(); }

    private:
      GenericStack s;                 // implementation
    };

As you can see, the `IntStack` and `CatStack` classes serve only to enforce strong typing. Only `int` pointers can be pushed onto an `IntStack` or popped from it, and only `Cat` pointers can be pushed onto a `CatStack` or popped from it. Both `IntStack` and `CatStack` are implemented in terms of the class `GenericStack`, a relationship that is expressed through layering (see Item 40), and `IntStack` and `CatStack` will share the code for the functions in `GenericStack` that actually implement their behavior. Furthermore, the fact that all `IntStack` and `CatStack` member functions are (implicitly) `inline` means that the runtime cost of using these interface classes is zip, zero, nada, nil.

But what if potential clients don't realize that? What if they mistakenly believe that use of `GenericStack` is more efficient, or what if they're just wild and reckless and think only wimps need type-safety nets? What's to keep them from bypassing `IntStack` and `CatStack` and going straight to `GenericStack`, where they'll be free to make the kinds of type errors C++ was specifically designed to prevent?

Nothing. Nothing prevents that. But maybe something should.

I mentioned at the outset of this Item that an alternative way to assert an is-implemented-in-terms-of relationship between classes is through private inheritance. In this case, that technique offers an advantage over layering, because it allows you to express the idea that `GenericStack` is too unsafe for general use, that it should be used only to implement other classes. You say that by protecting `GenericStack`'s member functions:

    class GenericStack {
    protected:
      GenericStack();
      ~GenericStack();

      void push(void *object);
      void * pop();

      bool empty() const;

    private:
      ...                             // same as above
    };

    GenericStack s;                   // error! constructor is
                                      // protected

    class IntStack: private GenericStack {
    public:
      void push(int *intPtr) { GenericStack::push(intPtr); }
      int * pop() { return static_cast<int*>(GenericStack::pop()); }
      bool empty() const { return GenericStack::empty(); }
    };

    class CatStack: private GenericStack {
    public:
      void push(Cat *catPtr) { GenericStack::push(catPtr); }
      Cat * pop() { return static_cast<Cat*>(GenericStack::pop()); }
      bool empty() const { return GenericStack::empty(); }
    };

    IntStack is;                     // fine

    CatStack cs;                     // also fine

Like the layering approach, the implementation based on private inheritance avoids code duplication, because the type-safe interface classes consist of nothing but inline calls to the underlying `GenericStack` functions.

Building type-safe interfaces on top of the `GenericStack` class is a pretty slick maneuver, but it's awfully unpleasant to have to type in all those interface classes by hand. Fortunately, you don't have to. You can use templates to generate them automatically. Here's a template to generate type-safe stack interfaces using private inheritance:

    template<class T>
    class Stack: private GenericStack {
    public:
      void push(T *objectPtr) { GenericStack::push(objectPtr); }
      T * pop() { return static_cast<T*>(GenericStack::pop()); }
      bool empty() const { return GenericStack::empty(); }
    };

This is amazing code, though you may not realize it right away. Because of the template, compilers will automatically generate as many interface classes as you need. Because those classes are type-safe, client type errors are detected during compilation. Because `GenericStack`'s member functions are protected and interface classes use it as a private base class, clients are unable to bypass the interface classes. Because each interface class member function is (implicitly) declared `inline`, no runtime cost is incurred by use of the type-safe classes; the generated code is exactly the same as if clients programmed with `GenericStack` directly (assuming compilers respect the `inline` request — see Item 33). And because `GenericStack` uses `void*` pointers, you pay for only one copy of the code for manipulating stacks, no matter how many different types of stack you use in your program. In short, this design gives you code that's both maximally efficient and maximally type safe. It's difficult to do better than that.

One of the precepts of this book is that C++'s features interact in remarkable ways. This example, I hope you'll agree, is pretty remarkable.

The insight to carry away from this example is that it could not have been achieved using layering. Only inheritance gives access to protected members, and only inheritance allows for virtual functions to be redefined. (For an example of how the existence of virtual functions can motivate the use of private inheritance, see Item 43.) Because virtual functions and protected members exist, private inheritance is sometimes the only practical way to express an is-implemented-in-terms-of relationship between classes. As a result, you shouldn't be afraid to use private inheritance when it's the most appropriate implementation technique at your disposal. At the same time, however, layering is the preferable technique in general, so you should employ it whenever you can.

Back to Item 41: Differentiate between inheritance and templates.
Continue to Item 43: Use multiple inheritance judiciously.