Private Inheritance

What is the difference between public, private, and protected inheritance in C++?

To answer that question, I'd like to describe member's accessors first in my own words. If you already know this, skip to the heading "next:".

There are three accessors that I'm aware of: public, protected and private.

Let:

class Base {
public:
int publicMember;
protected:
int protectedMember;
private:
int privateMember;
};
  • Everything that is aware of Base is also aware that Base contains publicMember.
  • Only the children (and their children) are aware that Base contains protectedMember.
  • No one but Base is aware of privateMember.

By "is aware of", I mean "acknowledge the existence of, and thus be able to access".

next:

The same happens with public, private and protected inheritance. Let's consider a class Base and a class Child that inherits from Base.

  • If the inheritance is public, everything that is aware of Base and Child is also aware that Child inherits from Base.
  • If the inheritance is protected, only Child, and its children, are aware that they inherit from Base.
  • If the inheritance is private, no one other than Child is aware of the inheritance.

When should I use C++ private inheritance?

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 // ...

What is private inheritance, and what issues(s) does it address?

The private inheritance models "is-implemented-in-terms-of". The meaning is similar to "has-a". The differences are:

  1. With private inheritance you don't need to write a wrapper (good for lazy programmers)

  2. "has-a" allows you better control, you can expose only a subset of the interface or change method names if you like.

  3. Private inheritance makes exception safety difficult, have a look at exceptional c++ for more information

  4. You really need private inheritance just when you want to use a protected members of your base class.

  5. Sometimes private inheritance is used in the mix-in class (Effective c++ memory management chapters)

My personal preference is using "has-a" for general purpose, I use private inheritance just after I have rule out other options.

private inheritance

From a common understanding of inheritance, C++’ “private inheritance” is a horrible misnomer: it is not inheritance (as far as everything outside of the class is concerned) but a complete implementation detail of the class.

Seen from the outside, private inheritance is actually pretty much the same as composition. Only on the inside of the class do you get special syntax that is more reminiscent of inheritance than composition.

There’s a caveat though: C++ syntactically treats this as inheritance, with all the benefits and problems that this entails, such as scope visibility and accessibility. Furthermore, C-style casts (but no C++ cast!) actually ignores visibility and thus succeeds in casting your Derived pointer to Base:

Base* bPtr = (Base*) new Derived();

Needless to say, this is evil.

C++: overriding public\private inheritance

If B inherits from A using public, can B override one of the functions and force it to be private?
NO

Eventhough the my_func1() is declared under priavte access specifier it can be still called through a pointer to class A, actually pointing to a object of class B

The call to my_func1() is evaluated at run time depending on the type of objected pointed by the pointer. At compile time the compile sees the my_func1() call as call to A::my_func1() and since A::my_func1() is public the compiler doesn't report only error. It is only at runtime that actual function call B::my_func1() is evaluated.

Ofcourse, You cannot directly call my_func1() through object of class B though because B::my_func1() is declared under Private Access specifier and You cannot access privately declared members from outside the class.

How about the other way around? if the inheritance type is private - can B force a specific function to be public?
NO

If you are calling my_func1() through a pointer of the Base class A, At compile time it is just evaluated as call to A::my_func1() which is Invalid since A::my_func1() is declared private inclass A`

What if A is pure abstract? does it make a difference?
NO
It makes no difference if the base class is Abstract or just polymorphic. Same rules will be applicable.

Would protected make any difference in any combination?
NO
As explained in first 2 Q's if you are calling a virtual function thorough pointer to Base class then at compile time the compiler only checks the access of that member function in Base class because compiler sees it as call to Base class member function. The actual call to the function is evaluated at run time and the feature is called Runtime Polymorphism or Dynamic polymorphism which is independent of the Access specifiers, which as a compile time construct.

So in conclusion,

overriding members of Base Class does not affect access

Why do we actually need Private or Protected inheritance in C++?

It is useful when you want to have access to some members of the base class, but without exposing them in your class interface. Private inheritance can also be seen as some kind of composition: the C++ faq-lite gives the following example to illustrate this statement

class Engine {
public:
Engine(int numCylinders);
void start(); // Starts this Engine
};

class Car {
public:
Car() : e_(8) { } // Initializes this Car with 8 cylinders
void start() { e_.start(); } // Start this Car by starting its Engine
private:
Engine e_; // Car has-a Engine
};

To obtain the same semantic, you could also write the car Class as follow:

class Car : private Engine {    // Car has-a Engine
public:
Car() : Engine(8) { } // Initializes this Car with 8 cylinders
using Engine::start; // Start this Car by starting its Engine
};

However, this way of doing has several disadvantages:

  • your intent is much less clear
  • it can lead to abusive multiple inheritance
  • it breaks the encapsulation of the Engine class since you can access its protected members
  • you're allowed to override Engine virtual methods, which is something you don't want if your aim is a simple composition

Public and private inheritance in C++

Because you can't see it:

class Base
{
public: virtual ~Base() {}
};

class PublicDerived: public Base
{ };

class PrivateDerived: private Base
{ };

int main()
{
PublicDerived publicD;
PrivateDerived privateD;

Base& base1 = publicD;
Base& base2 = privateD; // ERROR
}

So you can not use a PrivateDerived object where a Base object could be used.

So it will never act like a Base class object.

With private inheritance, when is it ok to upcast?

It all comes from the fact that foobar receives a Foo and is ignorant of the fact that Bar (privatly) inherits from Foo. This trait is taken care of by the callers:

  • Inside Bar's constructor, in order to call foobar with *this, a conversion is necessary; specifically, *this of type Bar needs to be converted to Foo&, which is possible since the caller is aware of the inheritance relation between the two types.
  • In main(), outside class Bar scope then, the call to foobar with b which is of type Bar also needs a conversion. But in this context, the relation between Bar and Foo is unknown, and there is no conversion possible.

Private inheritance means only the derived type knows of this inheritance. In its scope, everything happens as if it was a public inheritance. But outside the scope of the derived type, this relation is unknown and everything happens as if there was no inheritance at all.

private inheritance in C++

B can call public (and protected) methods of A, since A constructor is public B can call it.

Please see following link to better understand c++ private inheritance:
Difference between private, public, and protected inheritance

Does private inheritance always mean HAS-A?

You example can be implemented through composition like this:

class A {
private:
class B {
B(const B&) = delete;
B& operator=(const B&) = delete;
} b;
};

A is noncopyable, because its member b is noncopyable.



Related Topics



Leave a reply



Submit