HiveBrain v1.2.0
Get Started
← Back to all entries
patterncppMinor

Composition or Private Inheritance for Implementing Builder?

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
builderprivateinheritanceforimplementingcomposition

Problem

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) { myS

Solution

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.

Context

StackExchange Code Review Q#2268, answer score: 3

Revisions (0)

No revisions yet.