8
votes
\$\begingroup\$

Over on StackOverflow, I was asked if I could come up with an example where private inheritance would be preferred to composition (in C++). The following is the situation I described, and I was wondering which implementation you would prefer. Most of the references I've found to private inheritance are poor uses, and I agree that it is rarely useful.

Let's say you have a class Foo that should be immutable, but it's rather complicated to set up (maybe you're reading settings from a file), so you decide to create a separate class FooBuilder to set up your Foo objects for you. My solution (using private inheritance) is to declare an abstract interface:

class MutableFoo
{
  public:
     virtual void setValue(int n) = 0;
     virtual void setSomethingElse(string s) = 0;
};

And my original Foo class:

class Foo : private MutableFoo
{
  public:
     Foo(FooBuilder builder)
     {
         builder.build(this);
     }

     int value() const { return myValue; }
     string somethingElse() const { return mySomethingElse; }

  private:
     void setValue(int n) { myValue = n; }
     void setSomethingElse(string s) { mySomethingElse = s; }

     int myValue;
     string mySomethingElse;
};

And the FooBuilder:

class FooBuilder
{
   public:
     FooBuilder(string fileWithSettings);
     void build(MutableFoo *fooToBuild);
};

Now I can create read-only Foo objects without declaring them all to be const:

Foo aFoo(FooBuilder(aFileWithSettings));

A similar implementation using composition might look something like this:

class Foo
{
   public:
      Foo(FooData d);

      int value() const { return data.value(); }
      string somethingElse() const { return data.somethingElse(); }

   private:
      FooData data;
};

class FooData
{
  public:
    int value() const { return myValue; }
    int somethingElse() const { return mySomethingElse; }

    void setValue(int n) { myValue = n; }
    void setSomethingElse(string s) { mySomethingElse = s; }

  private:
    int myValue;
    string mySomethingElse;
};

class FooBuilder
{
  public:
    FooBuilder(string fileWithSettings);
    FooData getData() const;
};

Foo aFoo(FooBuilder(aFileWithSettings).getData());

I don't see much difference between these implementations as far as coupling is concerned (which is the complaint I see most frequently leveled against inheritance vs. composition). In fact, the version using inheritance may have less coupling, as both Foo and FooBuilder depend on an abstract interface (MutableFoo) instead of a concrete class FooData. Also, if we have lots of methods, the composition version will end up with lots of simple delegations, which is tedious if nothing else.

Which do you prefer? Have I found a reasonable use for private inheritance? Have you found other reasonable uses?

And finally, has anyone ever found a legitimate use for protected inheritance? :-P

\$\endgroup\$

2 Answers 2

3
votes
\$\begingroup\$

Herb Sutter in his book 'Exceptional C++', Item 24 (Uses and Abuses of Inheritance), discusses the issue, and cites the following reasons for using private inheritance (instead of containment):

  • Override a virtual function
  • Access to a protected member
  • Construct the used object before, or destroy it after, another base sub-object
  • Share a common virtual base class or override the construction of a virtual base class
  • We benefit substantially from the empty base class optimization
  • We need "controlled polymorphism" - LSP IS-A, but in certain code only

If one of these situations applies, then you must use private inheritance. Otherwise, containment is preferred.

The last of these reasons is cited as a possible reason for protected inheritance.

He also comments:

That's as complete a list as I can make of the reasons to use non-public inheritance. (In fact, just one additional point would make this a complete list of all reasons to use any kind of inheritance: We need public inheritance to express IS-A. [...])

The item occupies 8 pages.

\$\endgroup\$
3
votes
\$\begingroup\$

Your second case isn't really using composition. In my view composition requires that I'm making use of usually a few distinct object each of which has internal logic. Your FooData class has no logic. You are really implementing the parameter object pattern.

FooData basically consists of an object which holds all of the arguments that you would usually pass to a constructor. You are using FooData because there are too many parameters to configure. But as long as the object does nothing but hold argument you should implement it as a struct without getters/setters.

If you do that, I think your second case wins over the first case. It is simpler and doesn't make use of any unusual techniques.

\$\endgroup\$

Not the answer you're looking for? Browse other questions tagged or ask your own question.