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 thatBase
containspublicMember
. - Only the children (and their children) are aware that
Base
containsprotectedMember
. - No one but
Base
is aware ofprivateMember
.
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 ofBase
andChild
is also aware thatChild
inherits fromBase
. - If the inheritance is
protected
, onlyChild
, and its children, are aware that they inherit fromBase
. - If the inheritance is
private
, no one other thanChild
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:
With private inheritance you don't need to write a wrapper (good for lazy programmers)
"has-a" allows you better control, you can expose only a subset of the interface or change method names if you like.
Private inheritance makes exception safety difficult, have a look at exceptional c++ for more information
You really need private inheritance just when you want to use a protected members of your base class.
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 in
class 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 callfoobar
with*this
, a conversion is necessary; specifically,*this
of typeBar
needs to be converted toFoo&
, which is possible since the caller is aware of the inheritance relation between the two types. - In
main()
, outsideclass Bar
scope then, the call tofoobar
withb
which is of typeBar
also needs a conversion. But in this context, the relation betweenBar
andFoo
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
How to Check Whether Multiple Variables Are Equal to the Same Value
Run a Program with More Than One Source Files in Gnu C++ Compiler
When to Make a Type Non-Movable in C++11
What Is a Constant Reference? (Not a Reference to a Constant)
Unique Hardware Id in MAC Os X
Difference Between Using #Include<Filename> and #Include<Filename.H> in C++
What Is a Buffer Overflow and How to Cause One
Extra Qualification Error in C++
Checking Value Exist in a Std::Map - C++
Variadic Template in VS 2012 (Visual C++ November 2012 Ctp)
Adding List Items or Nodes in Linked List
Compare Double to Zero Using Epsilon
New to Xcode Can't Open Files in C++
C++11: Number of Variadic Template Function Parameters
Operator Overloading on Class Templates
What's the Difference Between the Win32 and _Win32 Defines in C++