C++中的继承(二)
文章目录
- 前言
- 多继承
- 虚继承
- 虚继承的底层
- 组合
前言
上一篇文章我们C++的正常继承其实已经讲完了,但是后面还有一个大坑。
实际当中继承有单继承和多继承。
单继承就是直接继承一个类。
只有一个直接父类的就叫做单继承。
如果是单继承那就比较简单。
现实世界除了有单继承还有多继承。
多继承
多继承就是我一个类我具备另外两个类的特征。
单继承就是一个类只具备另外一个类的特征。
现实世界当中有什么东西需要具备两个特征都继承一下呢?
比如:有没有一种物种既具有水果的特征,也具有蔬菜的特征?
番茄。
多继承很重要,它能够更好的描绘这个世界。
所以多继承看起是很合理的,但是它有一个大坑。
多继承就可能会导致这种菱形继承。
菱形继承会有什么样的问题呢?
他会导致对象里面有两份人的信息。
这样你就不知道要访问从学生那里继承来的呢,还是从老师那里继承来的呢?
指定访问是能解决二义性的
但是这样很不合理的。
首先名字肯定有一个正式的名字比较合理,另外如果有其他的一些信息,
你肯定会觉得很冗余,比如
数据冗余的本质是空间浪费
所以不要搞出菱形继承,非常非常坑。
虚继承
菱形继承怎样解决数据冗余和二义性呢?
这里引入了一个新的东西,虚继承。
它们都变成了同一个。所以也得出一个结论,监视窗口看到的不一定是真实的,
它们都是被处理过的。
从实际的角度,可以用多继承,但是不要用菱形继承。
但是从学习的角度,我们还得学一下这个菱形继承。
这样是不是菱形继承?
是的,它都有数据冗余和二义性。
虚继承的底层
虚继承是如何解决数据冗余和二义性的?
虚继承虽然解决了数据冗余和二义性,但是这个过程是很难看的。
监视窗口已经看不出它最真实的面目。它的底层不是这样的。
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std;
class Person
{
public:string _name; // 姓名
};
class Student : virtual public Person
{
protected:int _num; //学号
};
class Teacher : virtual public Person
{
protected:int _id; // 职工编号
};
class Assistant : public Student, public Teacher
{
protected:string _majorCourse; // 主修课程
};
void Test()
{// 这样会有二义性无法明确知道访问的是哪一个Assistant a;a._name = "peter";// 需要显示指定访问哪个父类的成员可以解决二义性问题,但是数据冗余问题无法解决a.Student::_name = "xxx";a.Teacher::_name = "yyy";
}int main()
{Test();return 0;
}
这里虽然有三个_name,但是每个_name都是一样的。
它的底层到底是怎么样呢?
物理上它的底层到底是怎么样呢?这里要换一个角度去看,
监视窗口已经看不到真实的东西,我们这里看一下内存窗口,内存窗口是真实的,不加修饰的。
我们这里用一个简化的类模型,方便我们看。
class A
{
public:int _a;
};
// class B : public A
class B : virtual public A
{
public:int _b;
};
// class C : public A
class C : virtual public A
{
public:int _c;
};
class D : public B, public C
{
public:int _d;
};
ABCD依次构成继承。
看它的底层是什么样的,我们先看不看虚继承,就看菱形继承。
接下来我们看虚继承。
对象模型相比刚才已经发生了本质的变化。
注意看这里面还有我们不认识的两个东西,这些东西是什么?
00 aa cd 8c
00 aa cb ac
这两个有点像指针,而且距离也不远
它们具体是什么呢,我们再用一个内存窗口观察一下。
注意这是小端,然后把它调成4,因为编译器是32位的,指针也是32位的,并且存的是整型,正好对齐方便观察。
这是怎么回事,这个地址指向的空间是个0, 并且下面有一个值。
这个值到底是什么?
所以这两个值是偏移量,也是相对距离。
之前是B里有一个a,C里也有一个a,那这就造成数据冗余和二义性。
现在把一个a放到公共的空间去,然后通过偏移量去找。
那现在问题来了,为什么不直接存a的地址呢?
直接存a的地址,这样不是更好吗?
大家注意,这个偏移量它没有存到第一个位置,这个位置是空出来的,为以后的
多态做准备。
如果这里存a地址,只解决了一个问题。而如果这个地方存放一个指针,指向一个表,这张表
可以存很多其他信息。
什么情况会涉及刚才这样一块问题呢?
以前的赋值兼容转换直接切割就可以了,现在直接切父类没毛病,但是不完整,还有一个a.
这个a在哪呢,在切的时候就涉及一个问题,找到对应的a。
怎么找呢?拿到对应的偏移量,然后计算才能找到a.
第二种就更复杂了。(这里还是比较难的)
ptrc指向哪里?
不是指向最开始的地方,多继承指针会发生偏移。
虚继承还有更复杂的问题。b对象的对象模型是什么样的?
按照我们以前的理解,b里面有一个_a,有个一个_b,现在实际并不是这样。
虚继承影响了这块。它要保持一致。
也就意味着这里面有两种情况,这两个代码看起来一样,实际上跑起来天差地别。
一个指向d对象,一个指向b对象。它们的偏移量也是不一样的。
但是它们的汇编指令是一样的。
它们去访问a是一样的,都是找第一个位置的地址。拿这个地址找到指向的表,
找到偏移量,然后计算找到a.
验证一下上面说的
一个是普通赋值,一个是切片
这样它的模型就对上了,它不需要区分是子类对象还是父类对象,它的动作是一样的。
汇编指令是一样的。
虚继承不是要解决数据冗余的问题吗?怎么还变大了?
这块变大了,是因为a太小了。它要解决数据冗余是有成本的,增加两个指针。
但是这个成本是固定的,而这个数据的大小是不确定的。
为什么不需要考虑指向的空间?
一个类可能定义很多很多对象,每个对象空间都要多8个字节,
但是这个空间不是每个对象独立的,是共同分担的,因为它们的偏移量是不变的。
真正的消耗并不在这里。
自己可以单独去验证一下。
小问题
1.如果A有多个成员,需不需要增加指针?
不需要,首先偏移量不会变,并且它是按照声明顺序去访问的。
内存对齐并不会影响这个。
举个例子。ptr是如何访问这些成员的?
这里也有内存对齐。编译器也是根据内存对齐的规则去算的。
写编译器的人真的是高手中的高手
虚继承是有一定的效率损失的。
在实际当中我们不要去玩菱形继承,效率上有损失而且出问题了很难分析。
看一下下面这道题,结果是什么,看一下你还想不想玩菱形继承。
这道题也没什么,就是在虚继承的基础上加入了构造函数。
这里打印顺序是什么?
这里面调用三次A的构造函数,难道打印了三次A吗?
打印三次A就意味着A被初始化三次。看起来好像这样。
编译器肯定做了很多特殊处理。
A的构造函数实际应该是调用一次,因为只有一份A.
现在还有一个问题,调的这个A,是B里的A,还是C里的A,还是单独的A?
肯定是D里面单独调用这个A最好。外面单独去搞更好。
这里面的运行顺序是怎样的呢?
为什么先调A?
因为初始化列表初始化的顺序跟出现的顺序无关,跟声明的顺序有关,
谁先声明谁先初始化。
注意,谁先被继承谁就先声明
这样出题难度更大。
实际结果没有变。
组合
什么是组合?举个例子。
D想复用C,可以像上面这样复用。
单从关系来说AB的继承关系更紧密一些,还是CD的组合关系更紧密一些?
也就是耦合度,继承的耦合度更高一些,为什么?
实际当中组合更好
我们之前的适配器就用了组合。
为什么还要用继承?
有些关系适合继承那就用继承。另外多态的基础必须是继承。
两个都可以那就用组合,适合用继承就用继承,
适合用组合就用组合。
容器里面有没有迭代器?
容器里面是没有迭代器的,除了vector.
容器只是通过begin()去获取那个位置的迭代器,并不是里面有。
相关文章:
C++中的继承(二)
文章目录 前言多继承虚继承虚继承的底层组合 前言 上一篇文章我们C的正常继承其实已经讲完了,但是后面还有一个大坑。 实际当中继承有单继承和多继承。 单继承就是直接继承一个类。 只有一个直接父类的就叫做单继承。 如果是单继承那就比较简单。 现实世界除了有…...
sklearn多项式回归和线性回归
什么是线性回归? 回归分析是一种统计学方法,用于研究自变量和因变量之间的关系。它是一种建立关系模型的方法,可以帮助我们预测和解释变量之间的相互作用。 回归分析通常用于预测一个或多个因变量的值,这些因变量的值是由一个或多…...
Postman报:400 Bad Request
● 使用Postman发送Post请求报400,入参为JSON; 二、分析 1、Postman请求并没有请求到后台Api(由于语法错误,服务器无法理解请求); 2、入参出错范围:cookie、header、body、form-data、x-www-f…...
apache poi_5.2.5 实现表格内某一段单元格的复制
apache poi_5.2.5 实现表格内,某一段单元格的复制。 实现思路 1.定位开始位置 2.从开始位置之后,在行索引集合中添加行索引下标 3.截至到结束位置。 4.对行索引集合去重,并循环行索引集合 5.利用XWPFTableRow对像的getCtRow().copy()方法&a…...
Oracle重建索引详解
更新:2023-05-17 18:08 一、Oracle重建索引命令 Oracle重建索引可以通过ALTER INDEX命令来完成。下面是示例代码: ALTER INDEX index_name REBUILD [PARAMETERS];其中,index_name是需要重建的索引名称,PARAMETERS是可选的重建参…...
众和策略证券开户首选:股票增持是好还是坏?大股东增持规定?
股票增持是好仍是坏? 股东增持在一定程度上反映股东对个股比较看好,大量的买单,增加了市场上的多方力气,会推动股价上涨,是一种利好消息。 一般大股东会增持可能是上市公司运营成绩较好,具有较大的发展前…...
UE4移动端最小包优化实践
移动端对于包大小有着严苛的要求,然而UE哪怕是一个空工程打出来也有90+M,本文以一个复杂的工程为例,探索怎么把包大小降低到最小。 一、工程简介 工程包含代码、插件、资源、iOS原生库工程。 二、按官方文档进行基础优化 官方文档 1、勾选Use Pak File和Create comp…...
用户管理第2节课--idea 2023.2 后端--实现基本数据库操作(操作user表) -- 自动生成
一、插件 Settings... 1.1 File -- Settings 1.2 Settings -- Plugins 1.2.1 搜索框,也可以直接搜索 1.3 Plugins -- 【输入 & 搜索】mybatis 1.3.1 插件不同功能介绍 1.3.2 翻译如下 1.4 选中 Update,更新下 1.4.1 更新中 1.4.2 Restart IDE 1…...
java开发面试:常见业务场景之单点登录SSO(JWT)、权限认证、上传数据的安全性的控制、项目中遇到的问题、日志采集(ELK)、快速定位系统的瓶颈
单点登录(SSO) 单点登录,Single Sign On(简称SSO),只需要登录一次,就可以访问所有信任的应用系统。 如果是单个tomcat服务,session可以共享,如果是多个tomcat,那么服务s…...
Java网络编程原理与实践--从Socket到BIO再到NIO
文章目录 Java网络编程原理与实践--从Socket到BIO再到NIOSocket基本架构Socket 基本使用简单一次发送接收客户端服务端 字节流方式简单发送接收客户端服务端 双向通信客户端服务端 多次接收消息客户端服务端 Socket写法的问题BIO简单流程BIO写法客户端服务端 BIO的问题 NIO简述…...
ARM GIC(三) gicv2架构
ARM的cpu,特别是cortex-A系列的CPU,目前都是多core的cpu,因此对于多core的cpu的中断管理,就不能像单core那样简单去管理,由此arm定义了GICv2架构,来支持多核cpu的中断管理 一、gicv2架构 GICv2,支持最大8个core。其框图如下图所示: 在gicv2中,gic由两个大模块组成: …...
第4章Netty第二节入门案例+channel,future,promise介绍
需求 开发一个简单的服务器端和客户端 客户端向服务器端发送 hello, world服务器仅接收,不返回 <dependency><groupId>io.netty</groupId><artifactId>netty-all</artifactId><version>4.1.39.Final</version> </d…...
【论文笔记】3D Gaussian Splatting for Real-Time Radiance Field Rendering
原文链接:https://arxiv.org/abs/2308.04079 1. 引言 网孔和点是最常见的3D场景表达,因其是显式的且适合基于GPU/CUDA的快速栅格化。神经辐射场(NeRF)则建立连续的场景表达便于优化,但渲染时的随机采样耗时且引入噪声…...
【生物信息学】层次聚类过程
文章目录 一、理论二、实践过程1过程2 一、理论 层次聚类是一种基于树状结构的聚类方法,它试图通过在不同层次上逐步合并或分裂数据集来构建聚类结构。这个树状结构通常被称为“树状图”(dendrogram),其中每个节点代表一个数据点或…...
变分自动编码器【03/3】:使用 Docker 和 Bash 脚本进行超参数调整
一、说明 在深入研究第 1 部分中的介绍和实现,并在第 2 部分中探索训练过程之后,我们现在将重点转向在第 3 部分中通过超参数调整来优化模型的性能。要访问本系列的完整代码,请访问我们的 GitHub 存储库在GitHub - asokraju/ImageAutoEncoder…...
KnowLM知识抽取大模型
文章目录 KnowLM项目介绍KnowLM项目的动机ChatGPT存在的问题 基于LLama的知识抽取的智析大模型数据集构建及训练过程预训练数据集构建预训练训练过程指令微调数据集构建 指令微调训练过程开源的数据集及模型局限性信息抽取Prompt 部署环境配置模型下载预训练模型使用LoRA模型使…...
MySQL数据库 索引
目录 索引概述 索引结构 二叉树 B-Tree BTree Hash 索引分类 索引语法 慢查询日志 索引概述 索引 (index)是帮助MySQL高效获取数据的数据结构(有序)。在数据之外,数据库系统还维护着满足特定查找算法的数据结构,这些数据结构以某种…...
ES 错误码
2xx状态码(如200)表示请求成功处理,并且不需要重试。 400状态码表示客户端发送了无效的请求,例如请求的语法有误或缺少必需的参数。在这种情况下,重试相同的请求很可能会导致相同的错误。因此,应该先检查并…...
听GPT 讲Rust源代码--src/tools(18)
File: rust/src/tools/rust-analyzer/crates/ide-ssr/src/from_comment.rs 在Rust源代码中的from_comment.rs文件位于Rust分析器(rust-analyzer)工具的ide-ssr库中,它的作用是将注释转换为Rust代码。 具体来说,该文件实现了从注…...
如何实现设备远程控制?
在工业自动化领域,设备远程控制是一项非常重要的技术。它使得设备可以在远离现场的情况下进行远程操作和维护,大大提高了设备的可用性和效率。 设备远程控制的应用场景有哪些? 远程故障排除:当设备出现故障时,工程师…...
百度侯震宇详解:大模型将如何重构云计算?
12月20日,在2023百度云智大会智算大会上,百度集团副总裁侯震宇以“大模型重构云计算”为主题发表演讲。他强调,AI原生时代,面向大模型的基础设施体系需要全面重构,为构建繁荣的AI原生生态筑牢底座。 侯震宇表示&…...
[Java]FileOutputStream的换行/续写/一次性写出一个字符串的方法
1.续写:FileOutputStream这个io流中的write方法默认情况下是覆盖写入的,如果需要追加写入,需要添加一个参数true 2.虽然write只能一个字符一个字符写入 但是我们可以把想输入的字符串放在str 再将str转化成byte数组 import java.io.FileOutp…...
VM进行TCP/IP通信
OK就变成这样 vm充当服务端的话也是差不多的操作 点击连接 这里我把端口号换掉了因为可能被占用报错了,如果有报错可以尝试尝试换个端口号 注: 还有一个点在工作中要是充当服务器,要去网络这边看下他的ip地址 拉到最后面...
剑指Offer 队列栈题目集合
目录 用两个栈实现队列 用两个栈实现队列 刷题链接: https://www.nowcoder.com/practice/54275ddae22f475981afa2244dd448c6 题目描述 思路一: 使用两个栈来实现队列的功能。栈 1 用于存储入队的元素,而栈 2 用于存储出队的元素。 1.push…...
grafana基本使用
一、安装grafana 1.下载 官网下载地址: https://grafana.com/grafana/download官网包的下载地址: yum install -y https://dl.grafana.com/enterprise/release/grafana-enterprise-10.2.2-1.x86_64.rpm官网下载速度非常慢,这里选择清华大…...
备份至关重要!如何解决iCloud的上次备份无法完成的问题
将iPhone和iPad备份到iCloud对于在设备发生故障或丢失时确保数据安全至关重要。但iOS用户有时会收到一条令人不安的消息,“上次备份无法完成。”下面我们来看看可能导致此问题的原因,如何解决此问题,并使你的iCloud备份再次顺利运行。 这些故…...
【项目问题解决】% sql注入问题
目录 【项目问题解决】% sql注入问题 1.问题描述2.问题原因3.解决思路4.解决方案1.前端限制传入特殊字符2.后端拦截特殊字符-正则表达式3.后端拦截特殊字符-拦截器 5.总结6.参考 文章所属专区 项目问题解决 1.问题描述 在处理接口入参的一些sql注入问题,虽然通过M…...
B/S医院手术麻醉临床管理系统源码 手术申请、手术安排
手术麻醉系统概述 手术室是医院各个科室工作交叉汇集的一个重要中心,在时间、空间、设备、药物、材料、人员调配的科学管理、高效运作、安全质控、绩效考核,都十分重要。手术麻醉管理系统(Operation Anesthesia Management System࿰…...
解锁高效工作!5款优秀工时管理软件推荐
工时管理,一直是让许多企业和团队头疼的问题。传统的纸质工时表、复杂的电子表格,不仅操作繁琐,还容易出错。幸好,随着科技的进步,我们迎来了工时管理软件的春天。今天,就让我们一起走进这个新时代…...
ICLR 2024 高分论文 | Step-Back Prompting 使大语言模型通过抽象进行推理
文章目录 一、前言二、主要内容三、总结🍉 CSDN 叶庭云:https://yetingyun.blog.csdn.net/ 一、前言 ICLR 2024 高分论文:《Step-Back Prompting Enables Reasoning Via Abstraction in Large Language Models》 论文地址:https://openreview.net/forum?id=3bq3jsvcQ1 …...
做网站的去哪找客户/百度seo排名教程
化到这一步,我们就将原来一个数据会非常大的A^B,变成了很多项的乘积。编程实现的时候,我们只需走一遍B的二进制位,并用一个变量a记录当前二进制位的权值,判断当前bi的值,然后将结果乘起来取模即可。快速幂取模通过将指…...
网站设计需要多久/有实力的网站排名优化软件
开始接触css动画的同学对于css33的transition属性以及transform属性会产生混淆,今天就借助小的demo来探讨一下这两者之间的关联和区别,希望可以让你有个更加清晰的认识; 首先我们来看一下什么是transition 在CSS 3引入Transition(…...
郑州网站建设学校/上海百度seo牛巨微
Hbase的安装部署 1、软件包的上传解压 2、修改hbase.env.sh 文件 配置JAVA_HOME 设置hbase使用外部zppkeeper export HBASE_MANAGES_ZKfalse 配置 hbase-site.xml 见讲义 hbase.zookeeper.property.dataDir配置的一定要是zookeeper的数据存…...
礼县建设局网站/深圳网络推广培训中心
几句话掌握子网掩码、ip地址、主机号、网络号、网络地址、广播地址191.172.16.10.33/27 中的/27也就是说子网掩码是255.255.255.224 即27个全12.从子网掩码255.255.255.252得出其网络位为30位,所以只有剩下的2位为主机位,主机位全零的为网络地址…...
重庆知名网络公司/百度首页排名优化价格
【神经网络与深度学习】卷积神经网络(CNN) 标签:【神经网络与深度学习】 实际上前面已经发布过一次,但是这次重新复习了一下,决定再发博一次。 说明:以后的总结,还应该以我的认识进行总结&#…...
html 修改 wordpress/十大成功营销策划案例
转自:http://hi.baidu.com/yufeng0103/blog/item/b5dc3225f8c43c6d35a80f41.htmlasp.net2.0新添加了对web.config直接操作的功能。开发的时候有可能用到在web.config里设置配置文件,其实是可以通过程序来设置这些配置节的。asp.net2.0需要添加引用&#…...