Inheritance — private
and protected
inheritance
How do you express “private
inheritance”?
When you use : private
instead of : public
. E.g.,
class Foo : private Bar {
public:
// ...
};
How are “private
inheritance” and “composition” similar?
private
inheritance is a syntactic variant of composition (AKA aggregation and/or has-a).
E.g., the “Car
has-a Engine
” relationship can be expressed using simple composition:
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
};
The “Car
has-a Engine
” relationship can also be expressed using private
inheritance:
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
};
There are several similarities between these two variants:
- In both cases there is exactly one
Engine
member object contained in everyCar
object - In neither case can users (outsiders) convert a
Car*
to anEngine*
- In both cases the
Car
class has astart()
method that calls thestart()
method on the containedEngine
object.
There are also several distinctions:
- The simple-composition variant is needed if you want to contain several
Engine
s perCar
- The
private
-inheritance variant can introduce unnecessary multiple inheritance - The
private
-inheritance variant allows members ofCar
to convert aCar*
to anEngine*
- The
private
-inheritance variant allows access to theprotected
members of the base class - The
private
-inheritance variant allowsCar
to overrideEngine
’svirtual
functions - The
private
-inheritance variant makes it slightly simpler (20 characters compared to 28 characters) to giveCar
astart()
method that simply calls through to theEngine
’sstart()
method
Note that private
inheritance is usually used to gain access into the protected
members of the base class, but this
is usually a short-term solution (translation: a band-aid).
Which should I prefer: composition or private inheritance?
Use composition when you can, private
inheritance when you have to.
Normally you don’t want to have access to the internals of too many other classes, and private
inheritance gives you
some of this extra power (and responsibility). But 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.
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-virtual
s in Wilma
, and Wilma
calls (usually pure virtuals) in
itself, which are overridden by Fred
. This would be much harder to do with composition.
class Wilma {
protected:
void fredCallsWilma()
{
std::cout << "Wilma::fredCallsWilma()\n";
wilmaCallsFred();
}
virtual void wilmaCallsFred() = 0; // A pure virtual function
};
class Fred : private Wilma {
public:
void barney()
{
std::cout << "Fred::barney()\n";
Wilma::fredCallsWilma();
}
protected:
virtual void wilmaCallsFred()
{
std::cout << "Fred::wilmaCallsFred()\n";
}
};
Should I pointer-cast from a private
derived class to its base class?
Generally, No.
From a member function or friend of a privately derived class, the relationship to the base class is known,
and the upward conversion from PrivatelyDer*
to Base*
(or PrivatelyDer&
to Base&
) is safe; no cast is needed or
recommended.
However users of PrivatelyDer
should avoid this unsafe conversion, since it is based on a private
decision of
PrivatelyDer
, and is subject to change without notice.
How is protected
inheritance related to private
inheritance?
Similarities: both allow overriding virtual
functions in the private
/protected
base class,
neither claims the derived is a kind-of its base.
Dissimilarities: protected
inheritance allows derived classes of derived classes to know about the inheritance
relationship. Thus your grand kids are effectively exposed to your implementation details. This has both benefits (it
allows derived classes of the protected
derived class to exploit the relationship to the protected
base class) and
costs (the protected
derived class can’t change the relationship without potentially breaking further derived
classes).
Protected inheritance uses the : protected
syntax:
class Car : protected Engine {
public:
// ...
};
What are the access rules with private
and protected
inheritance?
Take these classes as examples:
class B { /*...*/ };
class D_priv : private B { /*...*/ };
class D_prot : protected B { /*...*/ };
class D_publ : public B { /*...*/ };
class UserClass { B b; /*...*/ };
None of the derived classes can access anything that is private
in B
. In D_priv
, the public
and protected
parts of B
are private
. In D_prot
, the public
and protected
parts of B
are protected
. In D_publ
, the
public
parts of B
are public
and the protected
parts of B
are protected
(D_publ
is-a-kind-of-a B
).
class
UserClass
can access only the public
parts of B
, which “seals off” UserClass
from B
.
To make a public
member of B
public
in D_priv
or D_prot
, state the name of the member with a B::
prefix.
E.g., to make member B::f(int,float)
public
in D_prot
, you would say:
class D_prot : protected B {
public:
using B::f; // Note: Not using B::f(int,float)
};