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

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

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

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

表11.3 基类成员在派生类中的的访问属性
基类中的成员 在公用派生类中的访问属性 在私有派生类中的访问属性 在保护派生类中的访问属性
私有成员 不可访问 不可访问 不可访问
公用成员 公用 私有 保护
保护成员 保护 私有 保护

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

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

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

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

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

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

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

1) 在派生类中,成员有4种不同的访问属性:

  • 公用的,派生类内和派生类外都可以访问。
  • 受保护的,派生类内可以访问,派生类外不能访问,其下一层的派生类可以访问。
  • 私有的,派生类内可以访问,派生类外不能访问。
  • 不可访问的,派生类内和派生类外都不能访问。
表11.4 派生类中的成员的访问属性
派生类中的成员 在派生类中 在派生类外部 在下层公用派生类中
派生类中访问属性为公用的成员 可以 可以 可以
派生类中访问属性为受保护的成员 可以 不可以 可以
派生类中访问属性为私有的成员 可以 不可以 不可以
在派生类中不可访问的成员 不可以 不可以 不可以

需要说明的是:

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

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

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

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

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

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

  1. #include <iostream>
  2. #include <string>
  3. using namespace std;
  4. class Student//声明基类
  5. {
  6. public:
  7. //基类公用成员
  8. void display( );
  9. protected:
  10. //基类保护成员
  11. int num;
  12. string name;
  13. char sex;
  14. };
  15. //定义基类成员函数
  16. void Student::display( )
  17. {
  18. cout<<"num: "<<num<<endl;
  19. cout<<"name: "<<name<<endl;
  20. cout<<"sex: "<<sex<<endl;
  21. }
  22. class Student1: protected
  23. Student //用protected方式声明派生类Student1
  24. {
  25. public:
  26. void display1( );//派生类公用成员函数
  27. private:
  28. int age;//派生类私有数据成员
  29. string addr;//派生类私有数据成员
  30. };
  31. void Student1::display1( )//定义派生类公用成员函数
  32. {
  33. cout<<"num: "<<num<<endl;//引用基类的保护成员,合法
  34. cout<<"name: "<<name<<endl;//引用基类的保护成员,合法
  35. cout<<"sex: "<<sex<<endl;//引用基类的保护成员,合法
  36. cout<<"age: "<<age<<endl;//引用派生类的私有成员,合法
  37. cout<<"address: "<<addr<<endl; //引用派生类的私有成员,合法
  38. }
  39. int main( )
  40. {
  41. Student1 stud1; //stud1是派生类Student1类的对象
  42. stud1.display1( ); //合法,display1是派生类中的公用成员函数
  43. stud1.num=10023; //错误,外界不能访问保护成员
  44. return 0;
  45. }

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

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

详谈C++保护成员和保护继承的更多相关文章

  1. 虚基类——(1)定义人员类Person: 公有成员:姓名(Name); 保护成员:性别(Gender),年龄(Age); 构造函数和析构函数

    题目描述: (1)定义人员类Person: 公有成员:姓名(Name): 保护成员:性别(Gender),年龄(Age): 构造函数和析构函数 (2) 从人员类Person派生学生记录类Student ...

  2. java基础疑难点总结之成员变量的继承,方法重载与重写的区别,多态与动态绑定

    1.成员变量的继承 1.1要点 子类用extends关键字继承父类.子类中可以提供新的方法覆盖父类中的方法.子类中的方法不能直接访问父类中的私有域,子类可以用super关键字调用父类中的方法.在子类中 ...

  3. Java基础 成员变量的继承与覆盖

    通过继承可以得到父类的成员变量,子类的成员变量包括从父类继承的成员变量(包括从祖先类中继承的成员变量)以及子类中重新定义的成员变量.本次介绍内容包括:可以继承哪些成员?如果子类和父类出现了相同的成员变 ...

  4. python 私有和保护成员变量如何实现?—— "单下划线 " 开始的成员变量叫做保护变量,意思是只有类实例和子类实例能访问到这些变量;" 双下划线 " 开始的是私有成员,意思是只有类对象自己能访问,连子类对象也不能访问到这个数据

    默认情况下,Python中的成员函数和成员变量都是公开的(public),在python中没有类似public,private等关键词来修饰成员函数和成员变量.在python中定义私有变量只需要在变量 ...

  5. .NET程序内,访问私有或者保护成员的技巧

    如果是C++,我们可以计算对象内成员的位置,然后偏移指针以访问类型的所有非公开成员.但是.NET对象完全受GC管理,地址根本无法得到,并且也无法通过指针调用方法. 当然... 这是一种很不值得推荐的技 ...

  6. C# 对类中的保护成员进行写操作(邀请大家拍砖)

    假如我有一个类库 Lib,提供一个类 ClassA 对外服务,ClassA 中有若干只读属性 PropA, PropB 等等,外部调用者无法对 ClassA 中的 PropA 和 PropB 进行写操 ...

  7. Python基础(十二) 类私有成员和保护成员

    python中的protected和private python中用 _var :变量名前一个下划线来定义,此变量为保护成员protected,只有类及其子类可以访问.此变量不能通过from XXX ...

  8. PHP类的变量与成员,及其继承、访问与重写要注意的问题

    PHP的类及其实例: <?php ?>  后期静态绑定:为了避免子类重写静态属性后,使用继承来的方法仍然方法父类的静态属性,PHP5.3增加了一个新的语法,后期静态绑定,使用static关 ...

  9. C++学习之路—继承与派生(一):基本概念与基类成员的访问属性

    (本文根据<c++程序设计>(谭浩强)总结而成,整理者:华科小涛@http://www.cnblogs.com/hust-ghtao,转载请注明) 1   基本思想与概念 在传统的程序设计 ...

随机推荐

  1. 无法嵌入互操作类型“ESRI.ArcGIS.Display.SimpleFillSymbolClass”。请改用适用的接口。

    无法嵌入互操作类型"ESRI.ArcGIS.Display.SimpleFillSymbolClass".请改用适用的接口. 对于这样的问题 先看这个错误所对应的引用时那个,比如这 ...

  2. 一个酷炫的,基于HTML5,Jquery和Css的全屏焦点图特效,兼容各种浏览器

    基于HTML5和CSS的焦点图特效,梅花图案的背景很有中国特色,而且还会动哦,效果超炫,推荐下载! 演示图 html代码 <!DOCTYPE html PUBLIC "-//W3C// ...

  3. Quartz所使用的表的说明

    Quartz将Job保存在数据库中所需表的说明 QRTZ_CALENDARS 以 Blob 类型存储 Quartz 的 Calendar 信息 QRTZ_CRON_TRIGGERS 存储 Cron T ...

  4. 68. Text Justification

    题目: Given an array of words and a length L, format the text such that each line has exactly L charac ...

  5. JBPM4 常用表结构

    JBPM4 常用表结构 第一部分:表结构说明 Jbpm4 共有18张表,如下,其中红色的表为经常使用的表   一:资源库与运行时表结构 1.  JBPM4_DEPLOYMENT 流程定义表 2.  J ...

  6. (1)WinForm和WebForm

    如上所述,WinForm程序通常分为四层,而WebForm程序通常分为三层.   举例说明,winForm程序: IEnumerable<BatchUpdateResult<string, ...

  7. Java中boolean型变量的默认值问题

    1.首先分析Java中的三种不同变量的区别,如下表所示   概念 默认值 其他 类变量 也叫静态变量,是类中独立于方法之外的变量 用static 修饰 有默认初始值,系统自动初始化. 如boolean ...

  8. mysqldump批量导出(多张表)表结构及表数据

    Mysql 批量导出表结构(数据) 仅导出结构,不导出数据: 1.导出數據库為dbname的表结构    mysqldump  -h主机地址 -u用户名 -p密码 -d dbname >db.s ...

  9. How to install JDK (Java Development Kit) on Linux

    This tutorial will guide you on how to install JDK (Java Development Kit) on Linux. Since I use Cent ...

  10. UVa 10674 (求两圆公切线) Tangents

    题意: 给出两个圆的圆心坐标和半径,求这两个圆的公切线切点的坐标及对应线段长度.若两圆重合,有无数条公切线则输出-1. 输出是按照一定顺序输出的. 分析: 首先情况比较多,要一一判断,不要漏掉. 如果 ...