C++——派生类中的访问——可见性问题
C++中派生类对基类成员的访问形式主要有以下两种:
1、内部访问:由派生类中新增成员对基类继承来的成员的访问。
2、对象访问:在派生类外部,通过派生类的对象对从基类继承来的成员的访问。今天给大家介绍在3中继承方式下,派生类对基类成员的访问规则。
1、私有继承的访问规则
当类的继承方式为私有继承时,基类的public成员和protected成员被继承后成为派生类的private成员,派生类的其它成员可以直接访问它们,但是在类的外部通过派生类的对象无法访问。基类的private成员在私有派生类中是不可直接访问的,所以无论是派生类的成员还是通过派生类的对象,都无法直接访问从基类继承来的private成员,但是可以通过基类提供的public成员函数间接访问。私有继承的访问规则总结如下:
基类成员 private成员 public成员 protected成员
内部访问 不可访问 可访问 可访问
对象访问 不可访问 不可访问 不可访问
2、公有继承的访问规则
当类的继承方式为公有继承时,基类的public成员和protected成员被继承到派生类中仍作为派生类的public成员和protected成员,派生类的其它成员可以直接访问它们。但是,类的外部使用者只能通过派生类的对象访问继承来的public成员。基类的private成员在私有派生类中是不可直接访问的,所以无论是派生类成员还是派生类的对象,都无法直接访问从基类继承来的private成员,但是可以通过基类提供的public成员函数直接访问它们。公有继承的访问规则总结如下:
基类成员 private成员 public成员 protected成员
内部访问 不可访问 可访问 可访问
对象访问 不可访问 可访问 不可访问
3、保护继承的访问规则
当类的继承方式为保护继承时,基类的public成员和protected成员被继承到派生类中都作为派生类的protected成员,派生类的其它成员可以直接访问它们,但是类的外部使用者不能通过派生类的对象访问它们。基类的private成员在私有派生类中是不可直接访问的,所以无论是派生类成员还是通过派生类的对象,都无法直接访问基类中的private成员。保护继承的访问规则总结如下:
基类成员 private成员 public成员 protected成员
内部访问 不可访问 可访问 可访问
对象访问 不可访问 不可访问 不可访问
派生类中的访问——可见性问题
1、 对于在不同作用域声明的标识符,可见性原则:
若存在两个或多个具有包含关系的作用域,外层声明了一个标识符,而内层没有再次声明同名标识符,则外层标识符在内层仍然可见;
若在内层声明了同名标识符,则外层标识符在内层不可见,这时内层变量隐藏了外层的同名变量,这种现象称为隐藏规则。
其中,外层为基类,内层为派生类。
2、 作用域:
使用::作用域限定要访问的成员所在类的名称。
基类和派生类新增的成员都具有类作用域,但作用范围不同:是相互保护的两个层,派生类在内层。
(1)单继承中的同名隐藏
在没有使用虚函数的情况下,若派生类声明了一个和基类成员同名的新成员函数,即使函数的参数表不同,那么从基类继承的同名函数的所有重载形式也都被隐藏(外层基类中的同名成员函数被隐藏),使用成员名只能访问到派生类的成员函数。若要访问被隐藏的基类成员,必须使用基类名和作用域符::限定,使用基类名::成员名访问。
隐藏规则在私有继承中的应用
在私有继承时,为保证基类的公有成员能在派生类中访问,必须在派生类中重新声明同名的成员。在调用时,根据同名隐藏的规则,使用派生类中的函数。若对基类继承过来的某些函数功能进行扩充和改造,可以通过隐藏实现。
(2)多继承中的同名隐藏及访问冲突问题
①各基类没有任何继承关系,同时没有共同基类的情况:
在没有使用虚函数的情况下,若派生类的多个基类拥有同名的成员,同时派生类又新增了同名的成员函数时,派生类将隐藏所有基类的同名函数。
隐藏访问及隐藏冲突:
A 使用“对象名.成员名”可唯一标识和访问新增派生类成员;——隐藏
B 只有使用“对象名.基类名::成员名”这种作用域标识符可以访问基类的同名成员;
C若派生类没有声明同名函数,使用“对象名.成员名”无法唯一标示成员——冲突!
只能通过“对象名.基类名::成员名”访问基类的成员。
② 有间接基类的情况
A
B1 B2
C
对于派生类C,其直接基类B1、B2,间接基类A。
若B1 B2分别定义了同名的成员,而派生类C没有新增该同名函数,则使用“类C的对象名.成员名”产生冲突!只能使用“类C的对象名.B1/B2::成员名”可以访问B1/B2中的同名成员;但任何方式都无法访问A中的同名成员。(同①)
若要访问类A中的成员,而在B1 B 2 C中没有新增同名的成员,通过“类C的对象名.A中成员名”或“类C的对象名.A::A中成员名”访问类A中的成员,产生冲突!只有通过
“类C的对象名.B1/B2::成员名”访问类A中的成员。
若派生类C声明了同名函数,则使用“类C的对象名.成员名”访问的是C类新增的同名成员函数——隐藏
小结:
同名成员的唯一标识问题:
•使用作用域符::唯一标识派生类中由直接基类继承的成员;
派生类对象.直接基类名::同名成员/同名成员函数
•将共同基类设置为虚基类,这时从不同的路径继承过来的同名成员在内存中只要一个拷贝,同一个函数也只有一个路径。声明虚基类是在派生类定义过程中进行的:
class 派生类名:virtual 继承方式 基类名
C++——派生类中的访问——可见性问题的更多相关文章
- C++:调整基类成员在派生类中的访问属性的其他方法(同名成员和访问声明)
4.3 调整基类成员在派生类中的访问属性的其他方法 4.3.1 同名函数 在定义派生类的时候,C++语言允许在派生类中说明的成员与基类中的成员名字相同,也就是 说,派生类可以重新说明与基类成员同名的成 ...
- 3.3 C++改变基类成员在派生类中的访问属性
参考:http://www.weixueyuan.net/view/6360.html 总结: 使用using声明可以改变基类成员在派生类中的访问属性. private: using book::se ...
- 013_linuxC++之_派生类中权限的调整
(一)在上一篇012_LINUXC++之_类的继承定义中我们知道在派生类中可以访问public和protectd中的数据 (二)那么我们就可以在派生类中将上面两个中的数据进行权限的修改 (三)程序 # ...
- cc31a_demo--CppPrimer_静态成员与继承-在派生类中访问基类中的static成员的方法
//*基类中的static成员,在整个继承层次中只有一个实例 //*在派生类中访问基类中的static成员的方法 //1.基类名::成员名 //2.子类名::成员名 //3.对象.成员名 //4.指针 ...
- C++ 派生类成员的访问属性
派生类成员的访问属性: C++继承方式总共分为以下几种:public.private.protected三种(它们直接影响到派生类的成员.及其对象对基类成员访问的规则).(1)public(公有继承) ...
- C++继承 派生类中的内存布局(单继承、多继承、虚拟继承)
今天在网上看到了一篇写得非常好的文章,是有关c++类继承内存布局的.看了之后获益良多,现在转在我自己的博客里面,作为以后复习之用. ——谈VC++对象模型(美)简.格雷程化 译 译者前言 一个C ...
- c++中基类与派生类中隐含的this指针的分析
先不要看结果,看一下你是否真正了解了this指针? #include<iostream> using namespace std; class Parent{ public: int x; ...
- 06 - 从Algorithm 算法派生类中删除ExecuteInformation() 和ExecuteData() VTK 6.0 迁移
在先前的vtk中,如vtkPointSetAlgorithm 等算法派生类中定义了虚方法:ExecuteInformation() 和 ExecuteData().这些方法的定义是为了平稳的从VTK4 ...
- C#在派生类中调用基类成员
一.在派生类中调用基类成员 在C#的派生类中,我们可以使用base关键字调用基类中的公有或者受保护成员.这些成员只能是构造函数.实例方法或者实例属性. base关键字调用基类成员的语法格式如下: ba ...
随机推荐
- 004---os & sys
os模块和sys模块 这两个模块都提供了很多与操作系统之间交互的功能 使用 import os #当前脚本的工作目录,不是脚本目录 print(os.getcwd()) # 获取指定目录下的所有文件和 ...
- 阿里云mysql连接不上
轻量级服务器管理 - 防火墙 - 添加规则 防火墙 mysql 3306 注意IPtables 与 firewalld 状态! 啃爹的防火墙,找了一天
- 配置vue-yarm-PM2工具环境
步骤: 第一步:安装yarn 参考网址:https://yarn.bootcss.com/docs/install.html#linux-tab a.用pm2启动已创建的server.js #pm ...
- Python3爬虫(十一) 爬虫与反爬虫
Infi-chu: http://www.cnblogs.com/Infi-chu/ 一.重要概念 二.爬虫反爬虫进化论
- 【转】Python 数据库连接池
python编程中可以使用pymysql进行数据库连接及增删改查操作,但每次连接mysql请求时,都是独立的去请求访问,比较浪费资源,而且访问数量达到一定数量时,对mysql的性能会产生较大的影响.因 ...
- 将List中的数据更新到数据库中
List中有相应的数据,更新到数据库如下: 1.根据关键字查找后删除: foreach (var item in objSelList) { ADDaAn da = db.ADDaAns.Find(i ...
- elasticsearch-mathc和term的区分
elasticsearch和mysql在思想上是有不同的,elasticsearch有分词一说,比如北京奥运分词成北京,奥运,北京奥运.分词要要考虑两点,一个是查询字符串要不要分词,还有就是原存储字段 ...
- 【js笔记】数组那些事[0]
js中数组是一个特殊的对象,索引是它的属性,整数索引在内部被转化为字符串类型. 1 数组的创建 new关键字方法:var arr=new Array() var arr=new Array(10); ...
- npm命令 VS yarn命令
npm yarn 说明 npm init yarn init 在项目中引导创建一个package.json文件 npm install yarn install/yarn 安装所有依赖包(依据pa ...
- 分享 go语言爬虫---开源项目Pholcus
写在开头的话:记录一下最近学习Pholcus(https://github.com/henrylee2cn/pholcus)的过程,首先去学习的go基本语法,在没接触的时候发现很多不理解的地方,但是当 ...