Private inheritance, despite the name, isn’t really inheritance – at least not from the outside (of the class), where it matters.
For that reason, different rules apply. In C++, private inheritance is said to model an “is implemented in terms of” relationship. Thus, a priority queue which is implemented in terms of a heap, could look like this:
template <typename T, typename Comp = std::less<T> >
class priority_queue : private heap<T, Comp> {
// …
};
Personally, I don’t see the advantage of this pattern, and Neil has already stated that in most cases, composition actually has the advantage over private inheritance.
One advantage exists, though: since it’s such an established pattern, the meaning of a private inheritance is immediately clear to a seasoned C++ programmer; the above code would tell them that the priority queue is implemented in terms of a heap – which wouldn’t be obvious if the class just happened to use a heap as one of its members.
Private inheritance tends to get used in C++ primarily for policy classes. The classical example is allocators, which determine how a container class manages storage internally:
template <typename T, typename A = std::allocator<T> >
class vector : private A {
// …
};
No harm done. But once again, this could also have been done using composition.