深入分析C++派生类中的保护成员继承

protected 与 public 和 private 一样是用来声明成员的访问权限的。由protected声明的成员称为“受保护的成员”,或简称“保护成员”。从类的用户角度来看,保护成员等价于私有成员。但有一点与私有成员不同,保护成员可以被派生类的成员函数引用。

如果基类声明了私有成员,那么任何派生类都是不能访问它们的,若希望在派生类中能访问它们,应当把它们声明为保护成员。如果在一个类中声明了保护成员,就意味着该类可能要用作基类,在它的派生类中会访问这些成员。

在定义一个派生类时将基类的继承方式指定为protected的,称为保护继承,用保护继承方式建立的派生类称为保护派生类(protected derived class ), 其基类称为受保护的基类(protected base class ),简称保护基类。

保护继承的特点是:保护基类的公用成员和保护成员在派生类中都成了保护成员,其私有成员仍为基类私有。也就是把基类原有的公用成员也保护起来,不让类外任意访问。

保护基类的所有成员在派生类中都被保护起来,类外不能访问,其公用成员和保护成 员可以被其派生类的成员函数访问。

保护基类的所有成员在派生类中都被保护起来,类外不能访问,其公用成员和保护成员可以被其派生类的成员函数访问。

比较一下私有继承和保护继承(也就是比较在私有派生类中和在保护派生类中的访问属性), 可以发现,在直接派生类中,以上两种继承方式的作用实际上是相同的:在类外不能访问任何成员,而在派生类中可以通过成员函数访问基类中的公用成员和保护成员。但是如果继续派生,在新的派生类中,两种继承方式的作用就不同了。

例如,如果以公用继承方式派生出一个新派生类,原来私有基类中的成员在新派生类中都成为不可访问的成员,无论在派生类内或外都不能访问,而原来保护基类中的公用成员和保护成员在新派生类中为保护成员,可以被新派生类的成员函数访问。

大家需要记住:基类的私有成员被派生类继承(不管是私有继承、公有继承还是保护继承)后变为不可访问的成员,派生类中的一切成员均无法访问它们。如果需要在派生类中引用基类的某些成员,应当将基类的这些成员声明为protected,而不要声明为private。

如果善于利用保护成员,可以在类的层次结构中找到数据共享与成员隐蔽之间的结合点。既可实现某些成员的隐蔽,又可方便地继承,能实现代码重用与扩充。

通过以上的介绍,可以知道以下几点。

1) 在派生类中,成员有4种不同的访问属性:
公用的,派生类内和派生类外都可以访问。
受保护的,派生类内可以访问,派生类外不能访问,其下一层的派生类可以访问。
私有的,派生类内可以访问,派生类外不能访问。
不可访问的,派生类内和派生类外都不能访问。

需要说明的是:
这里所列出的成员的访问属性是指在派生类中所获得的访问属性。
所谓在派生类外部,是指在建立派生类对象的模块中,在派生类范围之外。
如果本派生类继续派生,则在不同的继承方式下,成员所获得的访问属性是不同的,在本表中只列出在下一层公用派生类中的情况,如果是私有继承或保护继承,大家可以从表11.3中找到答案。

2) 类的成员在不同作用域中有不同的访问属性,对这一点要十分清楚。一个成员的访问属性是有前提的,要看它在哪一个作用域中。有的读者问:“一个基类的公用成 员,在派生类中变成保护的,究竟它本身是公用的还是保护的?”应当说:这是同一个成员在不同的作用域中所表现出的不同特征。例如,学校人事部门掌握了全校师生员工的资 料,学校的领导可以查阅任何人的材料,学校下属的系只能从全校的资料中得到本系师生员工的资料,而不能查阅其他部门任何人的材料。如果你要问:能否查阅张某某的材料, 无法一概而论,必须查明你的身份,才能决定该人的材料能否被你“访问”。

在未介绍派生类之前,类的成员只属于其所属的类,不涉及其他类,不会引起歧义。 在介绍派生类后,就存在一个问题:在哪个范围内讨论成员的特征,同一个成员在不同 的继承层次中有不同的特征。为了说明这个概念,可以打个比方,汽车驾驶证是按地区核发的,北京的驾驶证在北京市范围内畅通无阻,如果到了外地,可能会受到某些限制,到了外国就无效了。同一个驾驶员在不同地区的权利是不同的。又譬如,到医院探视病人,如 果允许你进人病房近距离地看望病人并与之交谈,则可对病人了解比较深人;如果只允许你在玻璃门窗外探视,在一定距离外看到病人,只能对病人状况有粗略的印象;如果只允许在病区的走廊里通过电视看病人活动的片段镜头,那就更间接了。人们在不同的场合下对同一个病人,得到不同的信息,或者说,这个病人在不同的场合下的“可见性”不同。

平常,人们常习惯说某类的公用成员如何如何,这在一般不致引起误解的情况下是可以的。但是决不要误认为该成员的访问属性只能是公用的而不能改变。在讨论成员的访问属性时,一定要说明是对什么范围而言的,如基类的成员a,在基类中的访问属性是公用的,在私有派生类中的访问属性是私有的。

下面通过一个例子说明怎样访问保护成员。

[例] 在派生类中引用保护成员。

#include <iostream>
#include <string>
using namespace std;
class Student//声明基类
{
public:
  //基类公用成员
  void display( );
protected:
  //基类保护成员
  int num;
  string name;
  char sex;
};
//定义基类成员函数
void Student::display( )
{
  cout<<"num: "<<num<<endl;
  cout<<"name: "<<name<<endl;
  cout<<"sex: "<<sex<<endl;
}
class Student1: protected
Student //用protected方式声明派生类Student1
{
public:
  void display1( );//派生类公用成员函数
private:
  int age;//派生类私有数据成员
  string addr;//派生类私有数据成员
};
void Student1::display1( )//定义派生类公用成员函数
{
  cout<<"num: "<<num<<endl;//引用基类的保护成员,合法
  cout<<"name: "<<name<<endl;//引用基类的保护成员,合法
  cout<<"sex: "<<sex<<endl;//引用基类的保护成员,合法
  cout<<"age: "<<age<<endl;//引用派生类的私有成员,合法
  cout<<"address: "<<addr<<endl; //引用派生类的私有成员,合法
}
int main( )
{
  Student1 stud1; //stud1是派生类Student1类的对象
  stud1.display1( ); //合法,display1是派生类中的公用成员函数
  stud1.num=10023; //错误,外界不能访问保护成员
  return 0;
}

在派生类的成员函数中引用基类的保护成员是合法的。基类的保护成员对派生类的外界来说是不可访问的(例如,num是基类Student中的保护成员,由于派生类是保护继承,因此它在派生类中仍然是受保护的,外界不能用stud1.num来引用它),但在派生类内,它相当于私有成员,可以通过派生类的成员函数访问。可以看到,保护成员和私有成员不同之处,在于把保护成员的访问范围扩展到派生类中。

注意:在程序中通过派生类Student1的对象stud1的公用成员函数display1去访问基类的保护成员num、name和sex,不要误认为可以通过派生类对象名去访问基类的保护 成员(如stud1.num是错误的)。

私有继承和保护继承方式在使用时需要十分小心,很容易搞错,一般不常用,本教程后面的例子主要介绍公用继承方式。

(0)

相关推荐

  • C++ 类的继承与派生实例详解

     C++ 类的继承与派生实例详解 继承性是面向对象程序设计最重要的特性之一,使软件有了可重用性,C++提供的类的继承机制. 继承与派生的概念 一个新类从已有的类那里获得已有的特性,这种现象称为类的继承.同样也可以说成已有的类派生出来了新的类.类A继承自类B也就是类B派生了类A.所以继承和派生的关系就像小学时把字句和被字句的造句一样.有了继承与派生后,就有了父类/基类与子类/派生类,C++中将类B称为父类/基类,将类A称为子类/派生类. 派生类的声明: #include <iostream> u

  • 深入分析C++派生类中的保护成员继承

    protected 与 public 和 private 一样是用来声明成员的访问权限的.由protected声明的成员称为"受保护的成员",或简称"保护成员".从类的用户角度来看,保护成员等价于私有成员.但有一点与私有成员不同,保护成员可以被派生类的成员函数引用. 如果基类声明了私有成员,那么任何派生类都是不能访问它们的,若希望在派生类中能访问它们,应当把它们声明为保护成员.如果在一个类中声明了保护成员,就意味着该类可能要用作基类,在它的派生类中会访问这些成员.

  • 详谈C++中虚基类在派生类中的内存布局

    今天重温C++的知识,当看到虚基类这点的时候,那时候也没有太过追究,就是知道虚基类是消除了类继承之间的二义性问题而已,可是很是好奇,它是怎么消除的,内存布局是怎么分配的呢?于是就深入研究了一下,具体的原理如下所示: 在C++中,obj是一个类的对象,p是指向obj的指针,该类里面有个数据成员mem,请问obj.mem和p->mem在实现和效率上有什么不同. 答案是:只有一种情况下才有重大差异,该情况必须满足以下3个条件: (1).obj 是一个虚拟继承的派生类的对象 (2).mem是从虚拟基类派

  • 结合.net框架在C#派生类中触发基类事件及实现接口事件

    在派生类中引发基类事件 以下简单示例演示了在基类中声明可从派生类引发的事件的标准方法.此模式广泛应用于 .NET Framework 类库中的 Windows 窗体类. 在创建可用作其他类的基类的类时,应考虑如下事实:事件是特殊类型的委托,只可以从声明它们的类中调用.派生类无法直接调用基类中声明的事件.尽管有时需要事件仅由基类引发,但在大多数情形下,应该允许派生类调用基类事件.为此,您可以在包含该事件的基类中创建一个受保护的调用方法.通过调用或重写此调用方法,派生类便可以间接调用该事件. 注意:

  • C#类中属性与成员变量的使用小结

    属性实际上和成员变量没什么区别,属性代表类的某种特征, 让人更好理解而已. 使用中注意问题:1.属性名和变量名不能相同, 2.一般变量都是private,属性都是public的,属性用于给类外调用,变量限于类内使用,感觉封装性体现得要好些 3.属性必须和一个变量相联系,而这个变量必须要在类中定义.如果不定义,用成如下方法: 复制代码 代码如下: public int b //定义一个属性b  {      get   {    return b;   }   set   {    b = val

  • C++类中的特殊成员函数示例详解

    前言 C++类中有几个特殊的非静态成员函数,当用户未定义这些函数时,编译器将给出默认实现.C++11前有四个特殊函数,C++11引入移动语义特性,增加了两个参数为右值的特殊函数.这六个函数分别是: 1.默认构造函数 默认构造函数指不需要参数就能初始化的构造函数.包含无参和所有参数有默认值两种类型的构造函数. 2.复制构造函数 复制构造函数指使用该类的对象作为参数的构造函数.可以有其他参数,但必须提供默认值. 3.复制赋值运算符 重载等号=,将该类的对象赋值给已定义对象. 4.析构函数 没啥可说的

  • 深入解析C++中派生类的构造函数

    基类的构造函数不能被继承,在声明派生类时,对继承过来的成员变量的初始化工作也要由派生类的构造函数来完成.所以在设计派生类的构造函数时,不仅要考虑派生类新增的成员变量,还要考虑基类的成员变量,要让它们都被初始化. 解决这个问题的思路是:在执行派生类的构造函数时,调用基类的构造函数. 下面的例子展示了如何在派生类的构造函数中调用基类的构造函数. #include<iostream> using namespace std; //基类 class People{ protected: char *n

  • 详解C++中基类与派生类的转换以及虚基类

    C++基类与派生类的转换 在公用继承.私有继承和保护继承中,只有公用继承能较好地保留基类的特征,它保留了除构造函数和析构函数以外的基类所有成员,基类的公用或保护成员的访问权限在派生类中全部都按原样保留下来了,在派生类外可以调用基类的公用成员函数访问基类的私有成员.因此,公用派生类具有基类的全部功能,所有基类能够实现的功能, 公用派生类都能实现.而非公用派生类(私有或保护派生类)不能实现基类的全部功能(例如在派生类外不能调用基类的公用成员函数访问基类的私有成员).因此,只有公用派生类才是基类真正的

  • 解读C++编程中派生类的构成和创建

    C++派生类的构成 派生类中的成员包括从基类继承过来的成员和自己增加的成员两大部分.从基类继承的成员体现了派生类从基类继承而获得的共性,而新增加的成员体现了派生类的个性.正是这些新增加的成员体现了派生类与基类的不同,体现了不同派生类之间的区别. 在基类中包括数据成员和成员函数 (或称数据与方法)两部分,派生类分为两大部分:一部分是从基类继承来的成员,另一部分是在声明派生类时增加的部分.每一部分均分别包括数据成员和成员函数. 实际上,并不是把基类的成员和派生类自己增加的成员简单地加在一起就成为派生

  • C/C++中派生类访问属性详解及其作用介绍

    目录 保护继承 派生类成员的访问属性 总结 保护继承 由 protected 声明的成员称为 "受保护的成员", 或简称 "保护成员". 从用户的角度来看, 保护成员等价于私有成员. 保护成员可以被派生类的成员函数引用. 派生类成员的访问属性 4 种访问属性: 公用的: 类内和类外都可以访问 受保护的: 类内可以访问, 类外不能访问, 下一层的派生类可以访问 私有的: 类内可以访问, 类外不能访问 不可访问的: 类内和类外都不能访问 继承方式 基类中的成员 访问属性

  • C++派生类与基类的转换规则

    只有公用派生类才是基类真正的子类型,它完整地继承了基类的功能.基类与派生类对象之间有赋值兼容关系,由于派生类中包含从基类继承的成员,因此可以将派生类的值赋给基类对象,在用到基类对象的时候可以用其子类对象代替. 具体表现在以下几个方面: 派生类对象可以向基类对象赋值. 可以用子类(即公用派生类)对象对其基类对象赋值.如 A a1; //定义基类A对象a1 B b1; //定义类A的公用派生类B的对象b1 a1=b1; //用派生类B对象b1对基类对象a1赋值 在赋值时舍弃派生类自己的成员. 实际上

随机推荐