权限控制
Public inheritance
public inheritance means "is-a".
If you write that class D (“Derived”) publicly inherits from class B (“Base”), you are telling C++ compilers (as well as human readers of your code) that every object of type D is also an object of type B, but not vice versa.
-- 《Effective C++》item 32
Any function that expects an argument of type Person (or pointer-to-Person or reference-to-Person) will also take a Student object (or pointer-to-Student or reference-to-Student):
void eat(const Person& p); // anyone can eat
void study(const Student& s); // only students study
Person p; // p is a Person
Student s; // s is a Student
eat(p); // fine, p is a Person
eat(s); // fine, s is a Student, and a Student is-a Person
study(s); // fine
study(p); // error! p isn’t a Student
This is true only for public inheritance.
意味着只有公有继承,派生类的指针或引用才能转化为基类指针或引用
Public inheritance asserts that everything that applies to base class objects — everything! — also applies to derived class objects.
Things to Remember
✦ Public inheritance means “is-a.” Everything that applies to base classes must also apply to derived classes, because every derived class object is a base class object.
Private inheritance
Two features:
- in contrast to public inheritance, compilers will generally not convert a derived class object (such as Student) into a base class object (such as Person) if the inheritance relationship between the classes is private;
- members inherited from a private base class become private members of the derived class, even if they were protected or public in the base class.
see more in https://isocpp.org/wiki/faq/private-inheritance#overview-priv-inherit
Private inheritance means is-implemented-in-terms-of.
If you make a class D privately inherit from a class B, you do so because you are interested in taking advantage of some of the features available in class B, not because there is any conceptual relationship between objects of types B and D. As such, private inheritance is purely an implementation technique. (That’s why everything you inherit from a private base class becomes private in your class: it’s all just implementation detail.)
Private inheritance means that implementation only should be inherited; interface should be ignored.
派生类私有继承基类,旨在利用基类已经写好的一些功能,并不在意基类的接口,继承过来的成员统统变成私有。一般用于software implementation,而非software design.
Things to Remember
✦ Private inheritance means is-implemented-in-terms of. It’s usually inferior to composition, but it makes sense when a derived class needs access to protected base class members or needs to redefine inherited virtual functions.
✦ Unlike composition, private inheritance can enable the empty base optimization. This can be important for library developers who strive to minimize object sizes.
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).
What are the access rules with private
and protected
inheritance?
Take these calsses 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
, thepublic
andprotected
parts ofB
areprivate
; - In
D_prot
, thepublic
andprotected
parts ofB
areprotected
; - In
D_publ
, thepublic
parts ofB
arepublic
and theprotected
parts ofB
areprotected
(D_publ
is-a-kind-of-aB
); class
UserClass
can access only thepublic
parts ofB
, which “seals off”UserClass
fromB
.
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)
};
Conclusion
- 公有继承(public) 公有继承的特点是基类的公有成员和保护成员作为派生类的成员时,它们都保持原有的状态,而基类的私有成员仍然是私有的,不能被这个派生类的子类所访问。
- 私有继承(private) 私有继承的特点是基类的公有成员和保护成员都作为派生类的私有成员,并且不能被这个派生类的子类所访问。
- 保护继承(protected) 保护继承的特点是基类的所有公有成员和保护成员都成为派生类的保护成员,并且只能被它的派生类成员函数或友元访问,基类的私有成员仍然是私有的。
see more in C++继承:公有,私有,保护