[关闭]
@cxm-2016 2016-09-08T10:49:12.000000Z 字数 1679 阅读 2062

C++:私有继承

c++ no


公有继承是一种is-a的关系,而包含是一种has-a的关系。使用公有继承,基类的公有方法将成为派生类的公有方法。总之,派生类将继承基类的接口,这是is-a关系的一部分。然而C++中提供了另外一种实现has-a的方式——私有继承[1]

私有继承


使用私有继承,其基类的公有方法将成为派生类的私有方法。总之,派生类不继承基类的接口。

要进行私有继承,应该使用关键字private而不是public来定义类。实际上private是默认的类继承关系:

  1. class Student : private std::string{...};

初始化基类组件

隐式的继承组件而不是成员对象将影响代码的编写,因为再也不能使用name来描述对象了。而必须使用用于公有继承的技术。例如,对于构造函数:

  1. Student::Student(const char*str):name(str){}

对于使用私有继承的构造函数则成了这个样子:

  1. Student::Student(const char*str):std::string(str){};

访问基类方法

使用私有继承时,只能在派生类的方法中使用基类的方法。私有继承使得能够使用类名和作用域解析符来调用基类的方法:

  1. double Student::average() const{
  2. return Array::sum()/Array::size();
  3. }

访问基类对象

使用作用域解析符可以访问基类的方法,但是如果要使用基类对象本省,就需要强制类型转换。由于Student类是从stirng派生而来,因此可以通过强制类型转换,将Student对象转换为string对象

  1. const string & Student::Name() const{
  2. return (const string &)*this;
  3. }

访问基类友元函数

使用类名显式的限定函数名不适合于友元函数,这是因为友元不是类的成员。然而我们可以显式的转换为基类来正确的调用。

  1. ostream & operator<<(ostream &os ,const Student &stu){
  2. os<<(const string &)stu<<endl;
  3. }

应该使用包含还是继承


对于has-a的关系,我们既可以使用包含去实现,也可以使用私有继承实现,那么我们应该使用继承还是包含?
大多数程序猿倾向于使用包含,因为这样代码层次清晰,耦合度比继承低,是一种良好的设计模式。并且,继承会引起许多的问题,尤其是从多个基类继承时,需要多次的转型操作。然而,私有继承提供的特性比包含多。另一种情况是私有继承需要重新定义虚拟函数。派生类可以重定义虚函数,但包含不可以。

保护继承


保护继承是私有继承的一种变体。保护继承在列出基类时使用了protect关键字:

  1. class Student : protected std::string{...};

使用保护继承时,基类的公有成员和保护成员都成为派生类的保护成员。和私有继承一样,基类的接口在派生类中也是可用的,但是在继承层次结果之外是不可用的。

重新定义访问权限


当我们想要对外提供继承的方法时,可以采取两种方式
1,包装

  1. double Student::sum() const{
  2. return std::Array::sum();
  3. }

2,使用using重定义

  1. class Student : private std::Array{
  2. ...
  3. public:
  4. using std::Array::sum();
  5. using std::Array::average();
  6. ...
  7. };

各种继承方式的比较


特征 公有继承 保护继承 私有继承
公有成员变成 派生类的公有成员 派生类的保护成员 派生类的私有成员
保护成员变成 派生类的保护成员 派生类的保护成员 派生类的私有成员
私有成员变成 不可访问 不可访问 不可访问
能够隐式向上转型 能(只能在派生类内部) 不能

[1] Stephen Prata.C++ Primer Plus.人民邮电出版社.2016.3 543~550
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注