掘根宝典之C++包含对象的类,私有继承,保护继承,三大继承方式总结
包含对象成员的类
包含,组合和层次化:一个类里面的类成员之一是个类对象
我们来看个例子
#include<iostream>
using namespace std;
class AA
{
private:int a_;
public:AA(int a):a_(a){}void A(){cout << a_ << endl;}
};
class BB
{
private:AA t;int b_;
public:BB(int a,int b):t(a),b_(b){}void B(){t.a_ = 9;//不可以,a_是AA类的私有成员,在BB类无法直接使用t = { 9 };//可以cout << b_ << endl;t.A();//可以直接调用AA类的公有函数}
};
int main()
{BB t(2, 3);t.B();
}
这里的访问权限可能会让大家有一点绕。实际上并没有。
我们把AA类视为类,把BB类视为main函数,这样子BB类对AA类的访问权限就明白了。
私有继承
在C++中,私有继承是一种继承方式,它定义了一个私有派生类,也称为派生类。私有继承意味着派生类继承了基类的所有成员,但这些成员在派生类中是私有的,对外部不可见。
要进行私有继承请使用private关键字,或者不使用任何关键字(因为private是默认值,因此省略访问限定符也将导致私有继承)
格式如下
class 派生类名:private 基类名
{
}或者class 派生类名:基类名
{
}
使用私有继承时,只能在派生类的方法里使用基类的方法
私有继承允许使用类名和作用域解析运算符来调用基类的方法
我们看个例子
#include<iostream>
using namespace std;
class AA
{
private:int a_;
public:AA(int a):a_(a){}void A(){cout << a_ << endl;}
};
class BB :AA
{
private:int b_;
public:BB(int a,int b):AA(a),b_(b){}void B(){A();//可以AA::A();//可以}
};int main()
{BB r(2, 3);r.B();}
我们怎么通过派生类访问基类对象呢?当然是用强制类型转换
我们看个例子
#include<iostream>
using namespace std;
class AA
{
private:int a_;
public:AA(int a):a_(a){}void A(){cout << a_ << endl;}
};
class BB :AA
{
private:int b_;
public:BB(int a,int b):AA(a),b_(b){}AA& B(){return (AA&)*this;//派生类强制转换为基类}
};int main()
{BB r(2, 3);AA t=r.B();t.A();}
在私有继承中,未进行显式类型转换的派生类引用或指针,无法赋值给基类的引用或指针
#include<iostream>
using namespace std;
class AA
{
private:int a_;
public:AA(int a):a_(a){}void A(){cout << a_ << endl;}
};
class BB :AA
{
private:int b_;
public:BB(int a,int b):AA(a),b_(b){}};int main()
{BB r(2, 3);AA& t = r;//这是不行的AA* y = &r;//这是不行的
}
保护继承
保护继承是私有继承的变体。保护继承在列出基类时使用关键字protected:
class 派生类名:protected 基类名
{
}
使用保护继承时,基类的公有成员和保护成员都成为派生类的保护成员。和私有继承一样,基类的接口在派生类中也是可用的,但是在继承层次结构之外是不可用的。当从派生类派生出另一个类时,私有继承和保护继承的区别就体现出来了。使用私有继承时,第三代类将不能使用基类的接口,这是因为基类的公有方法在派生类中变成私有方法;使用保护继承时,基类的公有方法在第二代中变成受保护的,因此第三代派生类可以使用它们。
三种继承方式的比较
公有继承(public)继承、私有继承(private)、保护继承(protected)是常用的三种继承方式。
1.公有继承(public)
公有继承的特点是基类的公有成员和保护成员作为派生类的成员时,它们都保持原有的状态,而基类的私有成员仍然是私有的,不能被这个派生类的子类所访问。
2.私有继承(private)
私有继承的特点是基类的公有成员和保护成员都作为派生类的私有成员,并且不能被这个派生类的子类所访问。
3.保护继承
保护继承的特点是基类的所有公有成员和保护成员都成为派生类的保护成员,并且只能被它的派生类成员函数或友元访问,基类的私有成员仍然是私有的。
三种不同继承方式的基类特性和派生类特性
| 公有继承 | 保护继承 | 私有继承 | |
| 公有成员变为 | 派生类的公有成员 | 派生类的保护成员 | 派生类的私有成员 |
| 保护成员变成 | 派生类的保护成员 | 派生类的保护成员 | 派生类的私有成员 |
| 私有成员变为 | 只能通过基类接口访问 | 只能通过基类接口访问 | 只能通过基类接口访问 |
| 能否隐式向上转换 | 是 | 是(但只能在基类里) | 否 |
注:隐式向上转换:意味着无需进行显式类型转换,就可以将基类指针或引用指向派生类对象
在上图中:
1.基类成员对派生类都是:public和protected的成员是可见的,private的成员是不可见的。
2.基类成员对派生类的对象来说:要看基类的成员在派生类中变成了什么类型的成员。如:私有继承时,基类的公有成员和私有成员都变成了派生类中的私有成员,因此对于派生类中的对象来说基类的公有成员和私有成员就是不可见的。为了进一步理解三种不同的继承方式在其成员的可见性方面的区别,下面从三种不同角度进行讨论。
对于公有继承方式
1.基类成员对其对象的可见性:公有成员可见,其他不可见。这里保护成员同于私有成员。
2.基类成员对派生类的可见性:公有成员和保护成员可见,而私有成员不可见。这里保护成员同于公有成员。
3.基类成员对派生类对象的可见性:公有成员可见,其他成员不可见。
所以:在公有继承时,派生类的对象可以访问基类中的公有成员;派生类的成员函数可以访问基类中的公有成员和保护成员。这里,一定要区分清楚派生类的对 象和派生类中的成员函数对基类的访问是不同的。
对于私有继承方式
1.基类成员对其对象的可见性:公有成员可见,其他成员不可见
2.基类成员函数对派生类的可见性:公有成员和保护成员是可见的,而私有成员是不可见的。
3.基类成员对派生类对象的可见性:所有成员都是不可见的。
所以:在私有继承时,基类的成员只能由直接派生类访问,而无法向下继承。
对于保护继承方式
这种继承方式与私有继承方式的情况相同。两者的区别仅在于对派生类的成员而言,而对于基类成员有不同的可见性。(可见性也就是可访问性)。
关于可访问性还有另外一种说法。这种规则中,称派生类的对象对基类访问为水平访问,称派生类的派生类对基类的访问为垂直访问。
1 #include<iostream>2 class A{3 private:4 int privatedataA;5 protected:6 int protecteddataA;7 public:8 int publicdataA;9 };
10 //基类A的派生类B(公有继承)
11 class B :public A{
12
13 public:
14 void funcA()
15 {
16 int b;
17 b = privatedataA;
18 //错误:基类中的私有成员在派生类中不可见
19 b = protecteddataA;
20 //正确:基类的保护成员在派生类中是保护成员
21 b = publicdataA;
22 //正确:基类的公共成员在派生类是公共成员
23 }
24 };
25 //基类A的派生类C 私有继承
26 class C :private A{
27
28 public:
29 void funcA()
30 {
31 int c;
32 c = privatedataA;
33 //错误:基类中的私有成员在派生类中不可见
34 c = protecteddataA;
35 //正确:基类的保护成员在派生类中是私有成员
36 c = publicdataA;
37 //正确:基类的公共成员在派生类是私有成员
38 }
39 };
40 //基类A的派生类D 保护继承
41 class D :protected A{
42 public:
43 void funcA()
44 {
45 int d;
46 d = privatedataA;
47 //错误:基类中的私有成员在派生类中不可见
48 d = protecteddataA;
49 //正确:基类的保护成员在派生类中是保护成员
50 d = publicdataA;
51 //正确:基类的公共成员在派生类是保护成员
52 }
53 };
54 void main()
55 {
56 int value;
57 B objB;
58 value = objB.privatedataA;//错误:基类的私有成员在派生类不可见,对对象不可见
59 value = objB.protecteddataA;//错误:基类的保护成员在派生类中是保护成员,对对象不可见
60 value = objB.publicdataA;//错误:基类的公共成员在派生类中是公共成员,对对象可见
61
62 C objC;
63 value = objC.privatedataA;//错误:基类的私有成员在派生类不可见,对对象不可见
64 value = objC.protecteddataA;//错误:基类的保护成员在派生类中是私有成员,对对象不可见
65 value = objC.publicdataA;//错误:基类的公共成员在派生类中是私有成员,对对象不可见
66
67 D objD;
68 value = objD.privatedataA;//错误:基类的私有成员在派生类不可见,对对象不可见
69 value = objD.protecteddataA;//错误:基类的保护成员在派生类中是保护成员,对对象不可见
70 value = objD.publicdataA;//错误:基类的公共成员在派生类中是保护成员,对对象不可见
71 system("pause");
72 }
相关文章:
掘根宝典之C++包含对象的类,私有继承,保护继承,三大继承方式总结
包含对象成员的类 包含,组合和层次化:一个类里面的类成员之一是个类对象 我们来看个例子 #include<iostream> using namespace std; class AA { private:int a_; public:AA(int a):a_(a){}void A(){cout << a_ << endl;} }; class …...
第六篇:MySQL图形化管理工具
经过前五篇的学习,对于数据库这门技术的理解,我们已经在心中建立了一个城堡大致的雏形,通过命令行窗口(cmd)快速上手了【SQL语法-DDL-数据定义语言】等相关命令 道阻且长,数据库技术这一宝藏中还有数不清的…...
计算机网络——12DNS
DNS DNS的必要性 IP地址标识主机、路由器但IP地址不好记忆,不便于人类用使用(没有意义)人类一般倾向于使用一些有意义的字符串来标识Internet上的设备存在着“字符串”——IP地址的转换的必要性人类用户提供要访问机器的“字符串”名称由DN…...
vue3-应用规模化-工具链
工具链 项目脚手架 Vite Vite 是一个轻量级的、速度极快的构建工具,对 Vue SFC 提供第一优先级支持。作者是尤雨溪,同时也是 Vue 的作者! 要使用 Vite 来创建一个 Vue 项目,非常简单: (推荐)…...
EasyExcel动态列导出
测试代码地址:https://gitee.com/wangtianwen1996/cento-practice/tree/master/src/test/java/com/xiaobai/easyexcel/dynamiccolumn 官方文档:https://easyexcel.opensource.alibaba.com/docs/2.x/quickstart/write 一、实现方式 1、根据需要导出的列…...
JAVA面试题11
什么是Java的访问修饰符,并列出它们的作用。 Java的访问修饰符包括public、private、protected和默认。它们的作用如下: public: 可以被任何其他类访问。 private: 只能被所在类访问,其他类无法访问。 protected: 可以被所在类和同一个包中的…...
工业数据采集的时间不确定性及PLC-Recorder的通道偏移功能
目录 一、缘起 二、效果展示 三、设置方法 四、小结 一、缘起 大家都知道采集软件首先要尽可能还原数据原来的状态,给用户提供一个可以信赖的参考。但是,数据采集又有很多随机因素:Windows是一个周期不严格的系统、以太网通讯有时间波动、…...
十五、Object 类
文章目录 Object 类6.1 public Object()6.2 toString方法6.3 hashCode和equals(Object)6.4 getClass方法6.5 clone方法6.6 finalize方法 Object 类 本文为书籍《Java编程的逻辑》1和《剑指Java:核心原理与应用实践》2阅读笔记 java.lang.Object类是类层次结构的根…...
计算机网络——06分组延时、丢失和吞吐量
分组延时、丢失和吞吐量 分组丢失和延时是怎样发生的 在路由器缓冲区的分组队列 分组到达链路的速率超过了链路输出的能力分组等待排到队头、被传输 延时原因: 当当前链路有别的分组进行传输,分组没有到达队首,就会进行排队,从…...
[C#] 如何调用Python脚本程序
为什么需要C#调用python? 有以下几个原因需要C#调用Python: Python拥有丰富的生态系统:Python有很多强大的第三方库和工具,可以用于数据科学、机器学习、自然语言处理等领域。通过C#调用Python,可以利用Python的生态系…...
AlmaLinux更换鼠标样式为Windows样式
文章目录 前言先看看条件与依赖第一步:测试最终效果第二步:使用CursorXP修改鼠标样式CurosrXP安装CursorXP使用 第三步:Linux端环境搭建与命令执行UbuntuFedora其他系统均失败 第四步:应用主题 前言 只不过是突发奇想,…...
BUGKU-WEB 留言板
题目描述 题目无需登录后台!需要xss平台接收flag, http协议需要http协议的xss平台打开场景后界面如下: 解题思路 看到此类的题目,应该和存储型xss有关,也就是将恶意代码保存到服务器端即然在服务器端,那就…...
Linux之动静态库
今天我们来讲动静态库! 首先我们来粗粒度的划分一下动态库和静态库。 动态库就是只有一份库文件,所有想用该库的文件与改库文件建立链接,然后使用。这样可以提高代码复用率,避免重复拷贝产生没必要的内存消耗。 静态库…...
手机常亮屏不自动灭屏
一. 基础知识介绍 1. WakeLock(休眠锁) WakeLock用于保持设备的唤醒状态,有些情况下,即时用户不操作App,我们也需要保持屏幕处于唤醒状态,以保证用户体验,比如视频类APP和计步类APP,…...
JVM(1)基础篇
1 初始JVM 1.1 什么是JVM JVM 全称是 Java Virtual Machine,中文译名 Java虚拟机。JVM 本质上是一个运行在计算机上的程序,他的职责是运行Java字节码文件。 Java源代码执行流程如下: 分为三个步骤: 编写Java源代码文件。 使用…...
相机图像质量研究(12)常见问题总结:光学结构对成像的影响--炫光
系列文章目录 相机图像质量研究(1)Camera成像流程介绍 相机图像质量研究(2)ISP专用平台调优介绍 相机图像质量研究(3)图像质量测试介绍 相机图像质量研究(4)常见问题总结:光学结构对成像的影响--焦距 相机图像质量研究(5)常见问题总结:光学结构对成…...
[OPEN SQL] 删除数据
DELETE语句用于删除数据库表中的数据 本次操作使用的数据库表为SCUSTOM,其字段内容如下所示 航班用户(SCUSTOM) 需要删除以下数据 1.删除单条数据 语法格式 DELETE <dbtab> FROM <wa>. DELETE <dbtab> FROM TABLE <itab>. DELETE FROM &…...
C语言第二十五弹---字符函数和字符串函数(上)
✨个人主页: 熬夜学编程的小林 💗系列专栏: 【C语言详解】 【数据结构详解】 目录 1、字符分类函数 2、字符转换函数 3、strlen的使用和模拟实现 4、strcpy 的模拟实现 5、strcat 的模拟实现 6、strcmp 的模拟实现 7、strncpy 函数的使用 总结…...
寒假学习记录16:Express框架(Node)
后续会补充 1.引入express 1.先下载express框架 创建一个package.json格式的文件,里面写入 {"dependencies": {"express": "~4.16.1" //express版本号} } 然后打开终端输入 npm i 2.引入express模块 const express require(&quo…...
机器学习中的10种非线性降维技术对比总结
降维意味着我们在不丢失太多信息的情况下减少数据集中的特征数量,降维算法属于无监督学习的范畴,用未标记的数据训练算法。 尽管降维方法种类繁多,但它们都可以归为两大类:线性和非线性。 线性方法将数据从高维空间线性投影到低维空间(因此…...
KubeSphere 容器平台高可用:环境搭建与可视化操作指南
Linux_k8s篇 欢迎来到Linux的世界,看笔记好好学多敲多打,每个人都是大神! 题目:KubeSphere 容器平台高可用:环境搭建与可视化操作指南 版本号: 1.0,0 作者: 老王要学习 日期: 2025.06.05 适用环境: Ubuntu22 文档说…...
使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式
一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明:假设每台服务器已…...
未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?
编辑:陈萍萍的公主一点人工一点智能 未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战,在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…...
Cloudflare 从 Nginx 到 Pingora:性能、效率与安全的全面升级
在互联网的快速发展中,高性能、高效率和高安全性的网络服务成为了各大互联网基础设施提供商的核心追求。Cloudflare 作为全球领先的互联网安全和基础设施公司,近期做出了一个重大技术决策:弃用长期使用的 Nginx,转而采用其内部开发…...
反射获取方法和属性
Java反射获取方法 在Java中,反射(Reflection)是一种强大的机制,允许程序在运行时访问和操作类的内部属性和方法。通过反射,可以动态地创建对象、调用方法、改变属性值,这在很多Java框架中如Spring和Hiberna…...
Python如何给视频添加音频和字幕
在Python中,给视频添加音频和字幕可以使用电影文件处理库MoviePy和字幕处理库Subtitles。下面将详细介绍如何使用这些库来实现视频的音频和字幕添加,包括必要的代码示例和详细解释。 环境准备 在开始之前,需要安装以下Python库:…...
代理篇12|深入理解 Vite中的Proxy接口代理配置
在前端开发中,常常会遇到 跨域请求接口 的情况。为了解决这个问题,Vite 和 Webpack 都提供了 proxy 代理功能,用于将本地开发请求转发到后端服务器。 什么是代理(proxy)? 代理是在开发过程中,前端项目通过开发服务器,将指定的请求“转发”到真实的后端服务器,从而绕…...
Redis的发布订阅模式与专业的 MQ(如 Kafka, RabbitMQ)相比,优缺点是什么?适用于哪些场景?
Redis 的发布订阅(Pub/Sub)模式与专业的 MQ(Message Queue)如 Kafka、RabbitMQ 进行比较,核心的权衡点在于:简单与速度 vs. 可靠与功能。 下面我们详细展开对比。 Redis Pub/Sub 的核心特点 它是一个发后…...
佰力博科技与您探讨热释电测量的几种方法
热释电的测量主要涉及热释电系数的测定,这是表征热释电材料性能的重要参数。热释电系数的测量方法主要包括静态法、动态法和积分电荷法。其中,积分电荷法最为常用,其原理是通过测量在电容器上积累的热释电电荷,从而确定热释电系数…...
云原生安全实战:API网关Kong的鉴权与限流详解
🔥「炎码工坊」技术弹药已装填! 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 一、基础概念 1. API网关(API Gateway) API网关是微服务架构中的核心组件,负责统一管理所有API的流量入口。它像一座…...
