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

news2024/11/27 2:15:53

本文主要阐述关于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&);//可以访问_name
    friend 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.coloradmin.cn/o/460538.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Matlab——逻辑回归(原理、代码)

对于一个机器学习方法&#xff0c;通常由模型、策略和算法3个要素构成。 模型是假设空间的形式&#xff0c;如是线性函数还是条件概率&#xff1b;策略是判断模型好坏的数学表达式&#xff0c;将学习问题转化为优化问题&#xff0c;一般策略对应一个代价函数&#xff08;Cost F…

SQL优化(2):主键优化

在上一小节&#xff0c;我们提到&#xff0c;主键顺序插入的性能是要高于乱序插入的。 这一小节&#xff0c;就来介绍一下具体的 原因&#xff0c;然后再分析一下主键又该如何设计。 1 数据组织方式 在InnoDB存储引擎中&#xff0c;表数据都是根据主键顺序组织存放的&#xf…

数据结构——求二叉树的属性

数据结构——求二叉树的属性 一、对称性101. 对称二叉树1.递归2.迭代3.同类题&#xff1a; 二、深度104. 二叉树的最大深度1.递归1&#xff09;后序1&#xff09;前序 2.迭代&#xff08;层序&#xff09; 559. N 叉树的最大深度1.递归&#xff08;深度优先&#xff09;2.迭代&…

MATLAB实现OCR识别数字和字符

OCR也叫做光学字符识别&#xff0c;是计算机视觉研究领域的分支之一。它是利用光学技术和计算机技术把印在或写在纸上的文字读取出来&#xff0c;并转换成一种计算机能够接受、人又可以理解的格式。 MATLAB实现OCR识别数字和字符&#xff0c;涉及灰度转换、中值滤波、二值化处…

【教学类-34-05】拼图(彩色图片+凹凸拼)3*4格子(中班主题《个别化拼图》偏美术)

图片展示&#xff1a; 背景需求&#xff1a; 最近班级孩子得了传染病&#xff0c;来了2位孩子。 我觉得&#xff1a;人少的话&#xff0c;孩子们就有充足的时间去拼那些带有凹凸槽的自制彩色图形拼图。 难点&#xff1a; 1、从直线剪切&#xff08;方形拼图&#xff09;转…

[JAVA编] 一编让你搞定多态

目录 1. 多态概念 2. 多态的体现和实现条件 3. 重写 4. 引用类型转换 4.1向上转型 4.2向下转型 5. 多态的好处 1.多态的概念 什么是多态? 多态是继封装, 继承之后, 面向对象的三大特性 在生活中,比如跑的动作,猫,狗和大象,跑起来都不一样.再比如飞…

【cmd命令】MySQL服务器无法启动

winR 输入services.msc 我发现我电脑上有两个mysql名&#xff0c;上面一个&#xff08;MySQL&#xff09;处于停止运行状态 下面一个&#xff08;MySQL)处于运行状态 如果要使用上面一个的服务器&#xff0c;就要把下面一个的服务器关闭&#xff0c;然后启动上面的服务器…

elastic-job 搭建——应用于企业级项目

1. &#x1f4c2; 技术方案 方案介绍 ElasticJob 是面向互联网生态和海量任务的分布式调度解决方案。 它通过弹性调度、资源管控、以及作业治理的功能&#xff0c;打造一个适用于互联网场景的分布式调度解决方案&#xff0c;并通过开放的架构设计&#xff0c;提供多元化的作业…

你知道渲染农场是什么原理吗?它是如何工作的?

我们知道&#xff0c;仅靠一台计算机几乎是不能达到专业渲染集群的处理能力的。所以现在&#xff0c; 允许将很多台计算机或是处理器进行连接&#xff0c;再将连接后的机器作为一个总平台来处理不同的渲染需求&#xff0c;这样的设置&#xff0c;就被称之为渲染农场。 渲染农…

年轻人“赶烤”淄博,文旅业如何借势?

​&#xff08;图片来源于网络&#xff0c;侵删&#xff09; 文 | 螳螂观察 作者 | 易不二 从“更适合中国宝宝体质的TACO”在社交媒体爆火&#xff0c;到全国人民为之“赶烤”&#xff0c;淄博凭借独树一帜的烧烤文化&#xff0c;已经站上了文旅业回暖的潮头。 今年五一假期…

FPGA目前就业形势咋样?来听听业内工程师的看法

看到网上有一个问题很火&#xff1a;2023了&#xff0c;FPGA目前就业形势咋样?很多同学也对这个方向比较感兴趣&#xff0c;下面就来一起了解一下吧。 FPGA岗位有哪些&#xff1f; 从芯片设计流程来看&#xff0c;FPGA岗位可以分四类 产品开发期&#xff1a;FPGA系统架构师 …

基于FFmpeg倒放功能的实现-----命令行和API调用实现方法

来源:微信公众号「编程学习基地」 文章目录 FFmpeg API调用reverse滤镜实现视频倒放ffmpeg命令行实现方法FFmpeg 过滤器 调用API实现方法完整代码贴上运行FFmpeg API调用reverse滤镜实现视频倒放 ffmpeg命令行实现方法 ffmpeg -i bigbuckbunny_480x272.h265 -filter_comple…

vue页面内嵌iframe使用postMessage进行数据交互(postMessage跨域通信)

什么是postMessage postMessage是html5引入的API,它允许来自不同源的脚本采用异步方式进行有效的通信,可以实现跨文本文档,多窗口,跨域消息传递.多用于窗口间数据通信,这也使它成为跨域通信的一种有效的解决方案. vue父页面&#xff08;嵌入iframe的页面&#xff09; 在vue中…

【文心一言】文心一言最近这么火,它到底是什么

前言 文心一言&#xff08;英文名&#xff1a;ERNIE Bot&#xff09;是百度全新一代知识增强大语言模型&#xff0c;文心大模型家族的新成员&#xff0c;能够与人对话互动&#xff0c;回答问题&#xff0c;协助创作&#xff0c;高效便捷地帮助人们获取信息、知识和灵感。文心一…

网工容易混淆的三种网线类型:直连线、交叉线和反转线

网线是计算机网络中最常见的传输介质之一&#xff0c;它能够将数据快速而可靠地传输到各个网络设备中。在实际的网络应用中&#xff0c;我们常常需要使用到不同类型的网线&#xff0c;包括直连线、交叉线和反转线。本文将介绍这三种网线的定义、应用场景和注意事项。 直连线 …

Tailwind CSS入门(二)——基本介绍和特性

上一篇文章简要的介绍了原子类CSS&#xff0c;以及个人对语义化、原子化的一些经验和理解。从这篇文章开始&#xff0c;正式开始分享Tailwind CSS的特性、使用和技巧。 Tailwind CSS是一个为快速开发而精心设计的原子类CSS框架&#xff0c;在此我们将搭建一个Vite项目来配合讲…

力扣---LeetCode21. 合并两个有序链表(链表经典题)

文章目录 前言21. 合并两个有序链表链接&#xff1a;方法一&#xff1a;取小尾插1.1代码&#xff1a;1.2 流程图&#xff1a;1.3 注意&#xff1a; 方法二&#xff1a;带哨兵位2.1代码&#xff1a;2.2流程图&#xff1a; 总结 前言 焦虑不会消除明天的悲伤 只会让你今天的力量…

springboot概述

脚手架: 因为创建的为web项目&#xff0c;有这两个文件夹 在idea中也可以使用脚手架 会直接或间接包含依赖 启动类 单一模块: 启动类要放在根包下边&#xff0c;其他的业务放在根包或者根包的子包 多个模块: restController包含controller且每个方法都包含responseBody注解&…

这可能是你看过最详细的Java集合篇【二】—— LinkedList

文章目录 LinkedList继承关系数据结构变量构造方法添加元素相关方法查找元素相关方法删除元素相关方法清空方法遍历方法其它方法常见面试题 LinkedList LinkedList底层数据结构是双向链表。链表数据结构的特点是每个元素分配的空间不必连续、插入和删除元素时速度非常快、但访…

10年+工作经验总结:测试工程师职业成长路线图

一、功能测试工程师必备技能 1. 功能测试理论 主要包括&#xff1a; 软件测试流程 需求理解 测试用例设计&#xff08;编写测试用例的策略&#xff09; 执行测试用例 提交bug(bug是由什么组成&#xff0c;bug处理流程&#xff0c;bug优先级&#xff0c;bug的定位等) 回归…