When should I use C++ private inheritance?

C++Oop

C++ Problem Overview


Unlike protected inheritance, C++ private inheritance found its way into mainstream C++ development. However, I still haven't found a good use for it.

When do you guys use it?

C++ Solutions


Solution 1 - C++

I use it all the time. A few examples off the top of my head:

  • When I want to expose some but not all of a base class's interface. Public inheritance would be a lie, as Liskov substitutability is broken, whereas composition would mean writing a bunch of forwarding functions.
  • When I want to derive from a concrete class without a virtual destructor. Public inheritance would invite clients to delete through a pointer-to-base, invoking undefined behaviour.

A typical example is deriving privately from an STL container:

class MyVector : private vector<int>
{
public:
    // Using declarations expose the few functions my clients need 
    // without a load of forwarding functions. 
    using vector<int>::push_back;
    // etc...  
};
  • When implementing the Adapter Pattern, inheriting privately from the Adapted class saves having to forward to an enclosed instance.

  • To implement a private interface. This comes up often with the Observer Pattern. Typically my Observer class, MyClass say, subscribes itself with some Subject. Then, only MyClass needs to do the MyClass -> Observer conversion. The rest of the system doesn't need to know about it, so private inheritance is indicated.

Solution 2 - C++

Note after answer acceptance: This is NOT a complete answer. Read other answers like here (conceptually) and here (both theoretic and practic) if you are interested in the question. This is just a fancy trick that can be achieved with private inheritance. While it is fancy it is not the answer to the question.

Besides the basic usage of just private inheritance shown in the C++ FAQ (linked in other's comments) you can use a combination of private and virtual inheritance to seal a class (in .NET terminology) or to make a class final (in Java terminology). This is not a common use, but anyway I found it interesting:

class ClassSealer {
private:
   friend class Sealed;
   ClassSealer() {}
};
class Sealed : private virtual ClassSealer
{ 
   // ...
};
class FailsToDerive : public Sealed
{
   // Cannot be instantiated
};

Sealed can be instantiated. It derives from ClassSealer and can call the private constructor directly as it is a friend.

FailsToDerive won't compile as it must call the ClassSealer constructor directly (virtual inheritance requirement), but it cannot as it is private in the Sealed class and in this case FailsToDerive is not a friend of ClassSealer.


EDIT

It was mentioned in the comments that this could not be made generic at the time using CRTP. The C++11 standard removes that limitation by providing a different syntax to befriend template arguments:

template <typename T>
class Seal {
   friend T;          // not: friend class T!!!
   Seal() {}
};
class Sealed : private virtual Seal<Sealed> // ...

Of course this is all moot, since C++11 provides a final contextual keyword for exactly this purpose:

class Sealed final // ...

Solution 3 - C++

The canonical usage of private inheritance is the "implemented in terms of" relationship (thanks to Scott Meyers' 'Effective C++' for this wording). In other words, the external interface of the inheriting class has no (visible) relationship to the inherited class, but it uses it internally to implement its functionality.

Solution 4 - C++

One useful use of private inheritence is when you have a class that implements an interface, that is then registered with some other object. You make that interface private so that the class itself has to register and only the specific object that its registered with can use those functions.

For example:

class FooInterface
{
public:
    virtual void DoSomething() = 0;
};

class FooUser
{
public:
    bool RegisterFooInterface(FooInterface* aInterface);
};

class FooImplementer : private FooInterface
{
public:
    explicit FooImplementer(FooUser& aUser)
    {
        aUser.RegisterFooInterface(this);
    }
private:
    virtual void DoSomething() { ... }
};

Therefore the FooUser class can call the private methods of FooImplementer through the FooInterface interface, while other external classes cannot. This is a great pattern for handling specific callbacks that are defined as interfaces.

Solution 5 - C++

I think the critical section from the C++ FAQ Lite is:

> A legitimate, long-term use for private inheritance is when you want to build a class Fred that uses code in a class Wilma, and the code from class Wilma needs to invoke member functions from your new class, Fred. In this case, Fred calls non-virtuals in Wilma, and Wilma calls (usually pure virtuals) in itself, which are overridden by Fred. This would be much harder to do with composition.

If in doubt, you should prefer composition over private inheritance.

Solution 6 - C++

I find it useful for interfaces (viz. abstract classes) that I'm inheriting where I don't want other code to touch the interface (only the inheriting class).

[edited in an example]

Take the example linked to above. Saying that

> [...] class Wilma needs to invoke member functions from your new class, Fred.

is to say that Wilma is requiring Fred to be able to invoke certain member functions, or, rather it is saying that Wilma is an interface. Hence, as mentioned in the example

> private inheritance isn't evil; it's just more expensive to maintain, since it increases the probability that someone will change something that will break your code.

comments on the desired effect of programmers needing to meet our interface requirements, or breaking the code. And, since fredCallsWilma() is protected only friends and derived classes can touch it i.e. an inherited interface (abstract class) that only the inheriting class can touch (and friends).

[edited in another example]

This page briefly discusses private interfaces (from yet another angle).

Solution 7 - C++

Sometimes I find it useful to use private inheritance when I want to expose a smaller interface (e.g. a collection) in the interface of another, where the collection implementation requires access to the state of the exposing class, in a similar manner to inner classes in Java.

class BigClass;

struct SomeCollection
{
    iterator begin();
    iterator end();
};

class BigClass : private SomeCollection
{
    friend struct SomeCollection;
    SomeCollection &GetThings() { return *this; }
};

Then if SomeCollection needs to access BigClass, it can static_cast<BigClass *>(this). No need to have an extra data member taking up space.

Solution 8 - C++

I found a nice application for private inheritance, although it has a limited usage.

Problem to solve

Suppose you are given the following C API:

#ifdef __cplusplus
extern "C" {
#endif

    typedef struct
    {
        /* raw owning pointer, it's C after all */
        char const * name;

        /* more variables that need resources
         * ...
         */
    } Widget;
    
    Widget const * loadWidget();
    
    void freeWidget(Widget const * widget);
    
#ifdef __cplusplus
} // end of extern "C"
#endif

Now your job is to implement this API using C++.

C-ish approach

Of course we could choose a C-ish implementation style like so:

Widget const * loadWidget()
{
    auto result = std::make_unique<Widget>();
    result->name = strdup("The Widget name");
    // More similar assignments here
    return result.release();
}

void freeWidget(Widget const * const widget)
{
    free(result->name);
    // More similar manual freeing of resources
    delete widget;
}

But there are several disadvantages:

  • Manual resource (e.g. memory) management
  • It is easy to set up the struct wrong
  • It is easy to forget freeing the resources when freeing the struct
  • It is C-ish

C++ Approach

We are allowed to use C++, so why not use its full powers?

Introducing automated resource management

The above problems are basically all tied to the manual resource management. The solution that comes to mind is to inherit from Widget and add a resource managing instance to the derived class WidgetImpl for each variable:

class WidgetImpl : public Widget
{
public:
    // Added bonus, Widget's members get default initialized
    WidgetImpl()
        : Widget()
    {}

    void setName(std::string newName)
    {
        m_nameResource = std::move(newName);
        name = m_nameResource.c_str();
    }

    // More similar setters to follow

private:
    std::string m_nameResource;
};

This simplifies the implementation to the following:

Widget const * loadWidget()
{
    auto result = std::make_unique<WidgetImpl>();
    result->setName("The Widget name");
    // More similar setters here
    return result.release();
}

void freeWidget(Widget const * const widget)
{
    // No virtual destructor in the base class, thus static_cast must be used
    delete static_cast<WidgetImpl const *>(widget);
}

Like this we remedied all the above problems. But a client can still forget about the setters of WidgetImpl and assign to the Widget members directly.

Private inheritance enters the stage

To encapsulate the Widget members we use private inheritance. Sadly we now need two extra functions to cast between both classes:

class WidgetImpl : private Widget
{
public:
    WidgetImpl()
        : Widget()
    {}

    void setName(std::string newName)
    {
        m_nameResource = std::move(newName);
        name = m_nameResource.c_str();
    }

    // More similar setters to follow

    Widget const * toWidget() const
    {
        return static_cast<Widget const *>(this);
    }
    
    static void deleteWidget(Widget const * const widget)
    {
        delete static_cast<WidgetImpl const *>(widget);
    }

private:
    std::string m_nameResource;
};

This makes the following adaptions necessary:

Widget const * loadWidget()
{
    auto widgetImpl = std::make_unique<WidgetImpl>();
    widgetImpl->setName("The Widget name");
    // More similar setters here
    auto const result = widgetImpl->toWidget();
    widgetImpl.release();
    return result;
}

void freeWidget(Widget const * const widget)
{
    WidgetImpl::deleteWidget(widget);
}

This solution solves all the problems. No manual memory management and Widget is nicely encapsulated so that WidgetImpl does not have any public data members anymore. It makes the implementation easy to use correctly and hard (impossible?) to use wrong.

The code snippets form a compiling example on Coliru.

Solution 9 - C++

If you need a std::ostream with some small changes (like in this question) you may need to

  1. Create a class MyStreambuf which derives from std::streambuf and implement changes there
  2. Create a class MyOStream which derives from std::ostream that also initializes and manages an instance of MyStreambuf and passes the pointer to that instance to the constructor of std::ostream

The first idea might be to add the MyStream instance as a data member to the MyOStream class:

class MyOStream : public std::ostream
{
public:
    MyOStream()
        : std::basic_ostream{ &m_buf }
        , m_buf{}
    {}

private:
    MyStreambuf m_buf;
};

But base classes are constructed before any data members so you are passing a pointer to a not yet constructed std::streambuf instance to std::ostream which is undefined behavior.

The solution is proposed in Ben's answer to the aforementioned question, simply inherit from the stream buffer first, then from the stream and then initialize the stream with this:

class MyOStream : public MyStreamBuf, public std::ostream
{
public:
    MyOStream()
        : MyStreamBuf{}
        , basic_ostream{ this }
    {}
};

However the resulting class could also be used as a std::streambuf instance which is usually undesired. Switching to private inheritance solves this problem:

class MyOStream : private MyStreamBuf, public std::ostream
{
public:
    MyOStream()
        : MyStreamBuf{}
        , basic_ostream{ this }
    {}
};

Solution 10 - C++

Sometimes it could be an alternative to aggregation, for example if you want aggregation but with changed behaviour of aggregable entity (overriding the virtual functions).

But you're right, it has not many examples from the real world.

Solution 11 - C++

If derived class

  • needs to reuse code and
  • you can't change base class and
  • is protecting its methods using base's members under a lock.

then you should use private inheritance, otherwise you have danger of unlocked base methods exported via this derived class.

Solution 12 - C++

Private Inheritance to be used when relation is not "is a", But New class can be "implemented in term of existing class" or new class "work like" existing class.

example from "C++ coding standards by Andrei Alexandrescu, Herb Sutter" :- Consider that two classes Square and Rectangle each have virtual functions for setting their height and width. Then Square cannot correctly inherit from Rectangle, because code that uses a modifiable Rectangle will assume that SetWidth does not change the height (whether Rectangle explicitly documents that contract or not), whereas Square::SetWidth cannot preserve that contract and its own squareness invariant at the same time. But Rectangle cannot correctly inherit from Square either, if clients of Square assume for example that a Square's area is its width squared, or if they rely on some other property that doesn't hold for Rectangles.

A square "is-a" rectangle (mathematically) but a Square is not a Rectangle (behaviorally). Consequently, instead of "is-a," we prefer to say "works-like-a" (or, if you prefer, "usable-as-a") to make the description less prone to misunderstanding.

Solution 13 - C++

A class holds an invariant. The invariant is established by the constructor. However, in many situations it's useful to have a view of the representation state of the object (which you can transmit over network or save to a file - DTO if you prefer). REST is best done in terms of an AggregateType. This is especially true if you're const correct. Consider:

struct QuadraticEquationState {
   const double a;
   const double b;
   const double c;

   // named ctors so aggregate construction is available,
   // which is the default usage pattern
   // add your favourite ctors - throwing, try, cps
   static QuadraticEquationState read(std::istream& is);
   static std::optional<QuadraticEquationState> try_read(std::istream& is);

   template<typename Then, typename Else>
   static std::common_type<
             decltype(std::declval<Then>()(std::declval<QuadraticEquationState>()),
             decltype(std::declval<Else>()())>::type // this is just then(qes) or els(qes)
   if_read(std::istream& is, Then then, Else els);
};

// this works with QuadraticEquation as well by default
std::ostream& operator<<(std::ostream& os, const QuadraticEquationState& qes);

// no operator>> as we're const correct.
// we _might_ (not necessarily want) operator>> for optional<qes>
std::istream& operator>>(std::istream& is, std::optional<QuadraticEquationState>);

struct QuadraticEquationCache {
   mutable std::optional<double> determinant_cache;
   mutable std::optional<double> x1_cache;
   mutable std::optional<double> x2_cache;
   mutable std::optional<double> sum_of_x12_cache;
};

class QuadraticEquation : public QuadraticEquationState, // private if base is non-const
                          private QuadraticEquationCache {
public:
   QuadraticEquation(QuadraticEquationState); // in general, might throw
   QuadraticEquation(const double a, const double b, const double c);
   QuadraticEquation(const std::string& str);
   QuadraticEquation(const ExpressionTree& str); // might throw
}

At this point, you might just store collections of cache in containers and look it up on construction. Handy if there's some real processing. Note that cache is part of the QE: operations defined on the QE might mean the cache is partially reusable (e.g., c does not affect the sum); yet, when there's no cache, it's worth to look it up.

Private inheritance can almost always modelled by a member (storing reference to the base if needed). It's just not always worth it to model that way; sometimes inheritance is the most efficient representation.

Solution 14 - C++

Just because C++ has a feature, doesn't mean it's useful or that it should be used.

I'd say you shouldn't use it at all.

If you're using it anyway, well, you're basically violating encapsulation, and lowering cohesion. You're putting data in one class, and adding methods that manipulates the data in another one.

Like other C++ features, it can be used to achieve side effects such as sealing a class (as mentioned in dribeas' answer), but this doesn't make it a good feature.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionSashaView Question on Stackoverflow
Solution 1 - C++fizzerView Answer on Stackoverflow
Solution 2 - C++David Rodríguez - dribeasView Answer on Stackoverflow
Solution 3 - C++Harper ShelbyView Answer on Stackoverflow
Solution 4 - C++DaeminView Answer on Stackoverflow
Solution 5 - C++Bill the LizardView Answer on Stackoverflow
Solution 6 - C++biasView Answer on Stackoverflow
Solution 7 - C++Robert TuckView Answer on Stackoverflow
Solution 8 - C++BrandlingoView Answer on Stackoverflow
Solution 9 - C++BrandlingoView Answer on Stackoverflow
Solution 10 - C++baydaView Answer on Stackoverflow
Solution 11 - C++sportswithin.comView Answer on Stackoverflow
Solution 12 - C++Rahul_cs12View Answer on Stackoverflow
Solution 13 - C++lorroView Answer on Stackoverflow
Solution 14 - C++hasenView Answer on Stackoverflow