C++三大特性—继承 “访问控制”

news/2024/4/25 7:15:48/文章来源:https://blog.csdn.net/DEXTERFUTIAN/article/details/130311599

本文主要阐述关于C++继承中基类与派生类之间的访问关系


继承方式与访问方式

  • 继承定义格式:

在这里插入图片描述

   派生类可以继承定义在基类的成员,但是派生类的成员函数不一定有权访问从基类继承来的成员
   访问限定符的作用:控制派生类从基类继承而来的成员是否对派生类用户可见。

在这里插入图片描述

protected受保护的成员

一个类使用protected关键字的作用是希望与派生类分享但是不希望其它的公共成员访问它,可以看作是public与private取中的产物。

  • 与私有成员类似,protected成员对于类的用户是无法访问的(类外)
  • 与公共成员类似,protected成员对于派生类的成员和友元是可以访问的(类内)
  • 派生类的成员或友元只能通过派生类对象来访问基类的受保护成员,派生类对于一个基类对象中的受保护成员没有任何访问权限(大家可能感觉在这有点矛盾,且看下面分析)

对于派生类中的成员:

class person {person() {a = 10;}
protected:int a;
};class student : public person {person obj;void foo() {a = 11;obj.a = 12; }
};

在这里插入图片描述

   派生类中的成员函数想要“通过对象“来访问这个对象中的protected成员,那么这个对象必须要是派生类实例化出来的,不能是基类实例化出来的。因为基类实例化出来的对象,这个对象属于“类外”。
   如果是基类实例化出来的对象,那么派生类中的成员函数也只能访问这个基类对象的public成员,不能直接访问protected成员,没有特权。

对于派生类的友元:

class Person
{
protected:string _name;//受保护成员
};
class Student : public Person
{friend void fun1(Student&);//可以访问_namefriend void fun2(Person&); //不可以访问_name
protected:int _stunum;
};
void fun1(Student& a1)
{a1._name;
}
void fun2(Person& a2)
{a2._name;
}

在这里插入图片描述

派生类的成员和友元只能访问派生类对象中基类部分的受保护成员,对于普通的基类对象中的成员(类外)不具有特殊的访问权限。


共有、私有、受保护继承

某个类对其继承来的成员的访问权限受以下两个因素影响:

  • 基类中该成员的访问限定符
  • 派生类的派生列表中的访问限定符

1. 派生类可以访问基类的公有成员和受保护成员
   我们现在只需要了解派生类的作用域嵌套在基类的作用域之内,因此,对于一个派生类成员来说,使用派生类成员与使用基类成员的方式没有什么区别。

遵循基类的接口:
   每个类负责定义各自的接口,要想与类的交互必须使用该类的接口,即使这个对象是派生类的基类部分。
   派生类对象不能直接初始化基类的成员,虽然在语法上我们可以在构造函数体内给他的公有或保护的基类成员赋值,但是我们最好不这样做。派生类应该遵循基类的接口,通过调用基类的构造函数来初始化其基类部分。

继承关系分析:

class Person
{
public:void print(){cout << _age << endl;}
protected:string _name;
private:int _age;
};
class Student : public Person
{
public:int fun(){//public继承能访问protected成员cout << _name << endl;//不能访问private成员cout << _age << endl;}
};
class Teacher : private Person
{
public:int fun(){//private继承能访问protected成员cout << _name << endl;//不能访问private成员cout << _age << endl;}
};

2.派生访问说明符的目的是控制派生类用户(包括派生类的派生类在内)对于基类成员的访问权限

派生类的派生类:

class child : public Teacher
{
public:int fun(){//child继承于Teacher,Teacher是private继承于Person,//对于child来说Person的成员都是不可访问的cout << _name << endl;cout << _age << endl;}
};

派生类的实例化对象(用户):

    Student a1;  //Student是public继承Teacher a2;  //Teacher是private继承a1.print();  //对于其实例对象 public继承能访问基类的public成员a2.print();  //private继承 实例出的对象不能访问基类任何成员

3. 基类private成员在派生类中无论以什么方式继承都是不可见的。这里的不可见是指基类的私有成员还是被继承到了派生类对象中,但是语法上限制派生类对象不管在类里面还是类外面都不能去访问它
4.基类private成员在派生类中是不能被访问,如果基类成员不想在类外直接被访问,但需要在派生类中能访问,就定义为protected。可以看出保护成员限定符是因继承才出现的
5.使用关键字class时默认的继承方式是private,使用struct时默认的继承方式是public,不过最好显示的写出继承方式
6.在实际运用中一般使用都是public继承,几乎很少使用protetced/private继承,也不提倡使用protetced/private继承,因为protetced/private继承下来的成员都只能在派生类的类里面使用,实际中扩展维护性不强


派生类向基类转换的可访问性

派生类向基类的转换是否可访问由使用该转换的代码决定,同时派生类的派生访问说明符也会有影响。假设D继承自B

  • 只有当D公有(public)继承自B时,用户代码才能使用派生类向基类的转换,如果D继承自B的方式是受保护的或私有的,则用户不能使用该转换。

在这里插入图片描述

  • 不论D以什么方式继承B,D的成员函数和友元都能使用派生类向基类的转换。派生类向其直接基类的类型转换对于派生类的成员和友元来说永远可访问。

blog.csdnimg.cn/8db089391b8e4aa689475c4513007dfb.png)

  • 如果D继承B的方式是公有或受保护的,则D的派生类成员和友元可以使用D向B的类型转换;反之,如果D继承B的方式是私有,则不能使用。

**加粗样式**

对于代码中给定的节点来说,如果基类的公有成员是可访问的,则派生类向基类的类型转换也是可访问的,反之则不行。

类的设计与受保护成员:
   我们认为类有三种用户:普通用户、类的实现者、派生类
- 普通用户编写的代码使用类的对象,这部分代码只能访问类的公有(接口)成员
- 类的实现者负责编写类的成员和友元的代码,成员与友元既能访问公有也能访问私有
- 基类把希望派生类能够使用的部分声明为protected保护,普通用户不能使用受保护的成员,派生类及其友元依旧不能访问private私有成员
- 基类应该将其接口声明为公有,将属于自己实现的部分分为两类:一类可供派生类访问,另一组只能由基类或基类的友元访问。对于前者声明为protected保护,这样派生类就能使用基类的操作和数据,对于后者声明为private私有


如何改变个别成员的可访问性(using声明)

有时候我们需要改变派生类继承的某个名字的访问级别,可以通过使用using声明来达到这一目的

class Person
{
public:string _name; // 姓名string _sex;  // 性别int _age;     // 年龄
};
class Teacher : private Person
{
public:using Person::_name;
protected:using Person::_age;
private:using Person::_sex;int _No; // 学号
};

   因为Teacher使用了private私有继承,所以继承来的成员是Teacher的私有成员,但我们使用using声明语句改变了这些成员的可访问性,Teacher的用户将可以使用_name成员,Teacher的派生类也能使用_name与_age
   通过在类的内部使用using声明语句,我们可以将该类的直接或间接基类的任何可访问成员标记出来。using声明语句中名字的访问权限由该using声明语句之前的访问说明符决定,比如using Person::_sex; 我们声明在private下,所以它是private私有成员
在这里插入图片描述

派生类只能为那些在当前类中可以访问的名字提供using声明


如有错误或者不清楚的地方欢迎私信或者评论指出🚀🚀

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_103688.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

学习系统编程No.23【信号实战】

引言&#xff1a; 北京时间&#xff1a;2023/4/23&#xff0c;最近学习状态不怎么好&#xff0c;总是犯困&#xff0c;没精力的感觉&#xff0c;可能是病没有好彻底的原因&#xff0c;也可能是我内心因为生病而认为摆烂理所应当&#xff0c;反正最后导致摆烂&#xff0c;课现在…

android之 Launcher改造仿桌面排版的效果

一&#xff0c;背景 1.1 新接手一个灯光控制项目&#xff0c;其页面和效果还是比交复杂的&#xff0c;其中一个功能就是仿苹果桌面来排版灯具&#xff0c;支持拖拽&#xff0c;分组&#xff0c;分页。 拖动图标的时候判断是否空白位置还是已经有占位了&#xff0c;有的话就把…

体验了多款国产类ChatGPT产品后,我选择了道合顺的【ChatIC】

&#x1f482;作者简介&#xff1a; THUNDER王&#xff0c;一名热爱财税和SAP ABAP编程以及热爱分享的博主。目前于江西师范大学本科在读&#xff0c;同时任汉硕云&#xff08;广东&#xff09;科技有限公司ABAP开发顾问。在学习工作中&#xff0c;我通常使用偏后端的开发语言A…

springboot实用配置

springboot实用配置 &#xff08;一&#xff09;打包与运行&#xff08;二&#xff09;配置高级1.临时属性设置2.配置文件分类3.自定义配置文件 &#xff08;三&#xff09;多环境开发&#xff08;四&#xff09;日志1.日志基础2.日志输出格式控制3.日志文件 &#xff08;一&am…

14、RPC与gRPC

目录 一、rpc基础1 - rpc入门2 - 基础的rpc通信3 - 基于接口的RPC服务 二、rpc编码1 - gob编码2 - json on tcp3 - json on http&#xff08;待补充&#xff09; 三、prtotobuf编码1 - prtotobuf概述2 - protobuf编译器3 - 序列化和反序列化4 - 基于protobuf的RPC&#xff08;待…

vue项目 解决el-table自适应高度,vue页面不显示多条滚动条,超出的部分让el-table内部出现滚动条(推荐使用第二种解决方案)

一、需求 后台管理系统&#xff1a;最常见的页面都是由—>左侧菜单、头部tabView页签、主体数据渲染页面&#xff08;AppMain&#xff09;&#xff1b;而一般AppMain页面又分为&#xff1a; 搜索区域、table数据&#xff08;分页&#xff09;&#xff0c;可能也会存在底部&a…

QGIS数据可视化学习笔记01——一般的图层样式调整和在地图上添加图表

说明&#xff1a;QGIS数据可视化章节用的数据为QGIS绘制一张地图学习章节的数据&#xff0c;传送门&#xff1a;https://blog.csdn.net/qq_47188967/article/details/130196284 一、 一般的图层样式调整 首先呢&#xff0c;在QGIS中打开上一章节用的数据&#xff0c;界面如下&…

基于飞桨 PaddleVideo 的骨骼行为识别模型 CTR-GCN

main.pysame_seedsparse_argsmain ensemble.pyconfigs 文件夹Joint&#xff08;J&#xff09;的配置文件ctrgcn_fsd_J_fold0.yamlctrgcn_fsd_J_fold1.yaml Joint Angle&#xff08;JA&#xff09;的配置文件ctrgcn_fsd_JA_fold0.yaml paddlevideo 文件夹utils 文件夹__init__.p…

MATLAB符号运算(七) 更新中...

目录 1、实验目的&#xff1a; 2、实验内容&#xff1a; 1、实验目的&#xff1a; 1&#xff09;掌握定义符号对象和创建符号表达式的方法&#xff1b; 2&#xff09;掌握符号运算基本命令和规则&#xff1b; 3&#xff09;掌握符号表达式的运算法则以及符号矩阵运算&#xf…

[JavaEE初阶] 类加载机制

在真正的战争到来之前,尽可能地变得强大吧~ 文章目录 前言1. 类加载1.1 类加载的过程1.2 类加载的时机1.3 双亲委派模型 前言 这个问题是面试经典题,让我们来求甚解吧~ 1. 类加载 1.1 类加载的过程 如下图 加载,找到.class文件,读取文件内容验证,验证.class文件的格式是否…

SQL优化(3):order by优化

MySQL的排序&#xff0c;有两种方式&#xff1a; Using filesort : 通过表的索引或全表扫描&#xff0c;读取满足条件的数据行&#xff0c;然后在排序缓冲区sort buffer中完成排序操作&#xff0c;所有不是通过索引直接返回排序结果的排序都叫 FileSort 排序。 Using index :…

Spring lettuce读写分离

Redis 的 Sentinel 模式默认配置下 Redis 的客户端只对 Master 读写&#xff0c;另外2个Slave闲置。若主从节点在不同机房&#xff0c;在读取时会有跨机房的网络时延&#xff0c;并且比同机房访问更容易发生网络丢包。故在一些场景可以考虑将跨机房的服务节点设置为读写分离 Re…

Python中 re.findAll()、re.sub()、set()的使用

1. re.findall() re.findall()&#xff1a;函数返回包含所有匹配项的列表。返回string中所有与pattern相匹配的全部字串&#xff0c;返回形式为list / 数组。 由函数原型代码可知&#xff0c;findall() 函数存在三个参数&#xff1a; 1. pattern&#xff1a;正则表达式中的 ‘模…

Opencv+Python笔记(五)图像阈值化处理

图像阈值化可以理解为一个简单的图像分割操作&#xff0c;阈值又称为临界值&#xff0c;它的目的是确定出一个范围&#xff0c;然后这个范围内的像素点使用同一种方法处理&#xff0c;而阈值之外的部分则使用另一种处理方法或保持原样。 阈值处理有2种方式&#xff0c;一种是固…

订单交期迟滞,销售回应慢,怎么解决客户问题?

按客户定制产品订单&#xff0c;进行报价和生产的制造企业&#xff0c;有拆解图纸生成物料BOM的工序&#xff0c;通常由企业产品设计部门的拆图员岗位专门负责。 手工制作BOM数据&#xff0c;准确性低 拆图员肉眼查看每页图纸中的表格数据&#xff0c;手动敲键盘填入到企业要…

Android之 颜色选择器

一&#xff0c;简介 1.1 计算机的颜色通常有两种表示方式&#xff1a; 光源模式RGB(Red红, Green绿, Blue蓝)&#xff0c;数值0-255 印刷模式CMYK(Cyan青, Magenta品红, Yellow黄, Black黑)&#xff0c;数值1-100 任何颜色都是由RGB或CMYK混合出来的&#xff0c;再加上透明度…

【HTML+CSS+JS】登录注册页面大合集

前言 学JS也学了一段时间&#xff0c;正巧碰上了人工智能要调用人脸识别接口进行真人人脸识别&#xff0c;于是便萌生了用人脸来进行注册和登录的想法&#xff0c;这样的话就需要开发一个登录注册页面&#xff0c;然后用JS绑定注册事件调用人脸识别接口进行登录注册 饭要一口一…

【数据结构:线性表】单链表

在学习了顺序表&#xff0c;我们可能会对其有一些思考&#xff1a; 中间/头部的插入删除&#xff0c;时间复杂度为O(N)增容需要申请新空间&#xff0c;拷贝数据&#xff0c;释放旧空间。会有不小的消耗。增容一般是呈2倍的增长&#xff0c;势必会有一定的空间浪费。例如当前容…

【校招VIP】面试了一个抽奖的项目,我终于搞明白了,是8股文终于开始作恶了

最近因为招实习生&#xff0c;进行了很多次面试。 但面试的结果不尽人意。 就感觉今年的面试跟以前差距太大了。 直到经过这个同学的面试&#xff0c;我终于明白了是什么原因。 这个同学是南京一所211的研究生&#xff0c;他的项目经历是做了一个抽奖的微服务管理平台。 也…

10、Mysql常见面试题

Mysql常见面试题 文章目录 Mysql常见面试题一 Mysql索引001 Mysql如何实现的索引机制&#xff1f;002 InnoDB索引与MyISAM索引实现的区别是什么&#xff1f;003 一个表中如果没有创建索引&#xff0c;那么还会创建B树吗&#xff1f; 004 说一下B树索引实现原理&#xff08;数据…