cpp中的继承
一、继承概念
在cpp中,封装、继承、多态是面向对象的三大特性。这里的继承就是允许已经存在的类(也就是基类)的基础上创建新类(派生类或者子类),从而实现代码的复用。
如上图所示,Person是基类,Stu与Tea是派生类,Stu与Tea分别继承了基类中的对象,同时也有自己的类对象。
1.1派生类对基类的修改
派生类对象可以赋值给基类对象、基类指针、基类引用,这里的赋值只是把派生类中原本继承于父类的类对象赋值回去,对于派生类对象自己的类对象不会赋值。但是基类对象不能赋值给派生类对象。
如上图,派生类只能将基类中原有的(或者说继承过来的)_name和_gender赋值给父类,其余的无法赋值,如果是引用或指针,也是将派生类中基类对应的对象引用给或地址传给基类,基类修改时,子类也会受影响。
如上图,代码验证。注意,以上代码是在public继承时才会生效,如果换成protected时代码就会报错,protected继承下来的父类对象就是protected而非public,不支持修改的,private继承同理。
1.2父子类类成员变量、函数重名
当父类类成员变量名与子类成员变量名冲突时,默认时优先使用子类的。其实子列中也继承了父类中的重名变量,只不过将其隐藏,可以通过指定类成员名::变量名的方式访问。
再提一点,如果子类中没有实现Print函数而是依靠父类中的Print函数,那么打印结果会是这样的,如下图。
这是因为返回给父类的是一个Person类型的this指针,解引用访问的就是Person类中的_val.
当存在同名的函数名时,子类会调用自身的函数,也可以通过类名指定的方式进行访问。
如上图,这里A::func与B::func关系是隐藏,注意与函数重载区分(函数重载条件是同一作用域内函数名相同,参数列表不同构成重载)。
1.3派生类的默认成员函数
#include <iostream> using namespace std; class Person { public://构造函数Person() :_name("张三") {cout << "Person()" << endl;}//析构函数~Person() {cout << "~Person()" << endl;}//拷贝构造Person(const Person& p1):_name(p1._name) {cout << "Person(copy construct)" << endl;}Person& operator=(const Person& p1) {cout << "operator=" << endl;if (this != &p1) {this->_name = p1._name;}return *this;}public:string _name; };class Son :public Person { public:Son(const char* name = "", const string id = "111"):_id(id){}void display() {cout << _name << " " << _id << endl;} private:string _id; };int main() {Son s1;s1.display();return 0; }子类继承父类时会调用父类的构造函数来初始化继承过来的成员,然后子类在初始化自己的成员,同理对于析构、拷贝构造、赋值重载等都是同理。
如上图,s1会对继承的成员调用其对应的类的构造函数,当然,这也是我没有自定义时会调用父类的构造函数对其进行构造。
那么如何进行自定义构造_name呢?
如上图所示,通过son的构造函数对s1进行实例化构造,但是对于从父类继承下来的_name进行自定义时需要注意的是,在初始化_name时我们不能通过直接初始化的方式进行构造(如38行代码,这是错误的),而是通过父类的构造函数对父类成员进行初始化。在上图中也可以看见代码在初始化列表时(代码36行)就会调用父类的构造函数对_name进行初始化。
当然,也可以不自定义,此时_name就调用父类默认的构造函数对其进行初始化(前提是父类要有全缺省的构造函数,不然代码就会报错)。也可以使用初始化匿名对象的方式完成。
如上图所示,同时也要在父类中定义相对应的构造函数类型。
实现子类对象的拷贝构造函数
如上图,在实现子类的拷贝构造函数时,可以用子类类型的s来实例化Person,(这就是切片:父类可以提取子类中从父类继承来的_name进行初始化通过参数来初始化基类成员)
实现子类对象的赋值重载函数
如上图,实现子类对象的赋值重载函数时需要指明具体是哪一个重载函数,否则就会出现死循环,因为子类和父类出现同名函数时会优先调用子类的函数。代码第61行将Son类对象s进行切片,然后调用父类Person的重载函数将s中父类的部分切给Person完成赋值重载。
1.4继承与友元的关系
如上图所示,父类A的友元函数为display,子类B继承了父类A,此时友元函数只能访问子类的公开成员,对于受保护和私有的则无法访问。
1.5继承与静态成员
如上图,父类A中定义的静态成员变量在整个继承体系中都是存在的。
1.6菱形继承
如下图,A是B和C的父类,D又同时继承了B和C,此时D中含有基类成员_d和父类B(_b)和父类C(_c),同时B和C又同时含有A(_a),因此我们在访问_a时需要指定类域。
在上述图中可见,在开辟空间时,内存中64~68是父类B的空间,其中存放了B::_a和B::_b,对应的值就是1和3;而6C~70是父类C的空间,其中存放的就是C::_a和C::_C,对应的值就是2和4,最后一个位置就是D::_d。
如上图,整个44~54是类对象D的空间。
造成代码冗余与二义性问题
在上述代码中,子类D会同时存储了两份A的继承,分别是继承B和C的,这个就造成了代码冗余与内存消耗;其次当D访问A中成员时必须要指定具体哪个类中的(无法通过d._a方式访问)。解决方法就是虚拟继承。
如上图,通过虚拟继承的方法可以直接访问d._a,其实这里的B和C共享同一分A的继承,也就是说代码第91和92行对_a的修改是对同一个对象的修改(这一点在代码运行过程中可以看出)。
如上图所示,不难发现虽然_a是类中共享的一份区域,但是C和B区域与非虚拟继承相比又多出一块区域(如上图中绿色区域所示)。在分析内存时,0x0078FEAC指向的位置是0x00929bf4,0x0078FEC0指向的位置是0x00929c00,其内存图如下图所示
如上图所示,虽然0x00929bf4与0x00929c00指向的位置内容为空,但是其后一个位置的0000000c从十六进制转换为十进制刚好是12,其实这也就是C到_a的偏移量,这个表叫做虚基表,而只想虚机表的指针叫做虚机表指针。
相关文章:
cpp中的继承
一、继承概念 在cpp中,封装、继承、多态是面向对象的三大特性。这里的继承就是允许已经存在的类(也就是基类)的基础上创建新类(派生类或者子类),从而实现代码的复用。 如上图所示,Person是基类&…...
DeepSeek全栈接入指南:从零到生产环境的深度实践
第一章:DeepSeek技术体系全景解析 1.1 认知DeepSeek技术生态 DeepSeek作为新一代人工智能技术平台,构建了覆盖算法开发、模型训练、服务部署的全链路技术栈。其核心能力体现在: 1.1.1 多模态智能引擎 自然语言处理:支持文本生成(NLG)、语义理解(NLU)、情感分析等计算…...
CSS 真的会阻塞文档解析吗?
在网页开发领域,一个常见的疑问是 CSS 是否会阻塞文档解析。理解这一问题对于优化网页性能、提升用户体验至关重要。要深入解答这个问题,需要从浏览器渲染网页的原理说起。 浏览器渲染网页的基本流程 浏览器在接收到 HTML 文档后,会依次进行…...
大模型的UI自动化:Cline 使用Playwright MCP Server完成测试
大模型的UI自动化:Cline 使用Playwright MCP Server完成测试 MCP MCP(Model Context Protocol),是一个开发的协议,标准化了应用程序如何为大模型提供上下文。MCP提供了一个标准的为LLM提供数据、工具的方式,使用MCP会更容易的构建Agent或者是基于LLM的复杂工作流。 最近…...
碰撞检测 | 图解凸多边形分离轴定理(附ROS C++可视化)
目录 0 专栏介绍1 凸多边形碰撞检测2 多边形判凸算法3 分离轴定理(SAT)4 算法仿真与可视化4.1 核心算法4.2 仿真实验 0 专栏介绍 🔥课设、毕设、创新竞赛必备!🔥本专栏涉及更高阶的运动规划算法轨迹优化实战,包括:曲线…...
Python 基本数据类型
目录 1. 字符串(String) 2. 列表(List) 3. 字典(Dictionary) 4. 集合(Set) 5. 数字(Number) 6. 布尔值(Boolean) 1. 字符串&…...
突破“第一崇拜“:五维心理重构之路
一、视频介绍 在这个崇尚"第一"的时代,我们如何找到自己的独特价值?本视频将带您踏上五维心理重构之旅,从诗意人生的角度探讨如何突破"圣人之下皆蝼蚁"的局限。我们将穿越人生的不同阶段,从青春的意气风发到…...
KubeKey一键安装部署k8s集群和KubeSphere详细教程
目录 一、KubeKey简介 二、k8s集群KubeSphere安装 集群规划 硬件要求 Kubernetes支持版本 操作系统要求 SSH免密登录 配置集群时钟 所有节点安装依赖 安装docker DNS要求 存储要求 下载 KubeKey 验证KubeKey 配置集群文件 安装集群 验证命令 登录页面 一、Ku…...
UE5网络通信架构解析
文章目录 前言一、客户端-服务器架构(C/S Model)二、对等网络架构(P2P,非原生支持)三、混合架构(自定义扩展)四、UE5网络核心机制 前言 UE5的网络通信主要基于客户端-服务器(C/S&am…...
实验3 知识表示与推理
实验3 知识表示与推理 一、实验目的 (1)掌握知识和知识表示的基本概念,理解其在AI中的深刻含义与意义; (2)熟悉AI中常用的知识表示方法的优缺点及其应用场景; (3)掌握产…...
基于Springboot银行信用卡额度管理系统【附源码】
基于Springboot银行信用卡额度管理系统 效果如下: 系统登陆页面 用户个人中心页面 新增信用卡申请页面 评估审核页面 管理员主页面 评估审核页面 操作日志管理页面 消费页面 研究背景 随着金融行业的快速发展和信息技术的不断进步,信用卡作为一种便捷…...
达梦数据库学习笔记@1
目录 达梦数据库学习笔记一、表空间管理(一)默认表空间(二)相关数据字典(三)表空间操作(四)临时表空间管理 二、重做日志管理(一)系统视图(二&…...
图像处理篇---图像处理中常见参数
文章目录 前言一、分贝(dB)的原理1.公式 二、峰值信噪比(PSNR, Peak Signal-to-Noise Ratio)1.用途2.公式3.示例 三、信噪比(SNR, Signal-to-Noise Ratio)1.用途2.公式3.示例 四、动态范围(Dyna…...
AI Agent实战:打造京东广告主的超级助手 | 京东零售技术实践
前言 自2022年末ChatGPT的问世,大语言模型(LLM)技术引发全球关注。在大模型技术落地的最佳实践中,智能体(Agent)架构显现出巨大潜力,成为业界的普遍共识,各大公司也纷纷启动Agent技…...
50周学习go语言:第1周 环境搭建
以下是为零基础学习者准备的详细第1周教程,包含环境搭建、工具配置和首个Go程序的完整操作指南: 一、Go语言环境安装(Windows/macOS/Linux通用) 1. 下载安装包 官网地址:https://go.dev/dl//根据系统选择对应版本&am…...
4. MySQL 逻辑架构说明
4. MySQL 逻辑架构说明 文章目录 4. MySQL 逻辑架构说明1. 逻辑架构剖析1.1 服务器处理客户端请求1.2 Connectors(连接器)1.3 第1层:连接层1.4 第2层:服务层1.5 第3层:引擎层1.6 存储层 2. SQL执行流程2.1 MySQL 中的 SQL 执行流程 2.2 MySQL…...
《AI与NLP:开启元宇宙社交互动新纪元》
在科技飞速发展的当下,元宇宙正从概念逐步走向现实,成为人们关注的焦点。而在元宇宙诸多令人瞩目的特性中,社交互动体验是其核心魅力之一。人工智能(AI)与自然语言处理(NLP)技术的迅猛发展&…...
面对STM32的庞大体系,如何避免迷失在细节中?
我第一次接触STM32时,我以为抱着开发板就是拥抱未来,实际上一开机就喜提四大耳光,看到卖家演示的MP3播放、TFT彩屏、网口通信好炫酷,忍不住买回来掌握这些神技,到最后发现最实用的还是开发板的关机键和复位键。 看视频…...
ragflow-RAPTOR到底是什么?请通俗的解释!
RAPTOR有两种不同的含义,具体取决于上下文: RAPTOR作为一种信息检索技术 RAPTOR是一种基于树状结构的信息检索系统,全称为“Recursive Abstractive Processing for Tree-Organized Retrieval”(递归抽象处理树组织检索)…...
Linux系统移植之Uboot启动流程
Linux系统移植之Uboot启动流程 一,Uboot启动流程1.Uboot的两阶段1.1.第一阶段1.11.硬件初始化1.12.复制 U-Boot 到 RAM1.13.跳转到第二阶段 1.2.第二阶段1.21.C 语言环境初始化1.22. 硬件设备初始化1.23. 加载环境变量1.24. 显示启动信息1.25. 等待用户输入…...
全球首个30米分辨率湿地数据集(2000—2022)
数据简介 今天我们分享的数据是全球30米分辨率湿地数据集,包含8种湿地亚类,该数据以0.5X0.5的瓦片存储,我们整理了所有属于中国的瓦片名称与其对应省份,方便大家研究使用。 该数据集作为全球首个30米分辨率、覆盖2000–2022年时间…...
在Ubuntu中设置开机自动运行(sudo)指令的指南
在Ubuntu系统中,有时需要在系统启动时自动执行某些命令,特别是需要 sudo权限的指令。为了实现这一功能,可以使用多种方法,包括编写Systemd服务、配置 rc.local文件或使用 cron任务计划。本文将详细介绍这些方法,并提供…...
python如何将word的doc另存为docx
将 DOCX 文件另存为 DOCX 格式(Python 实现) 在 Python 中,你可以使用 python-docx 库来操作 Word 文档。不过需要注意的是,.doc 是旧的 Word 格式,而 .docx 是新的基于 XML 的格式。python-docx 只能处理 .docx 格式…...
GC1808高性能24位立体声音频ADC芯片解析
1. 芯片概述 GC1808是一款24位立体声音频模数转换器(ADC),支持8kHz~96kHz采样率,集成Δ-Σ调制器、数字抗混叠滤波器和高通滤波器,适用于高保真音频采集场景。 2. 核心特性 高精度:24位分辨率,…...
Mysql中select查询语句的执行过程
目录 1、介绍 1.1、组件介绍 1.2、Sql执行顺序 2、执行流程 2.1. 连接与认证 2.2. 查询缓存 2.3. 语法解析(Parser) 2.4、执行sql 1. 预处理(Preprocessor) 2. 查询优化器(Optimizer) 3. 执行器…...
NPOI操作EXCEL文件 ——CAD C# 二次开发
缺点:dll.版本容易加载错误。CAD加载插件时,没有加载所有类库。插件运行过程中用到某个类库,会从CAD的安装目录找,找不到就报错了。 【方案2】让CAD在加载过程中把类库加载到内存 【方案3】是发现缺少了哪个库,就用插件程序加载进…...
Vue 模板语句的数据来源
🧩 Vue 模板语句的数据来源:全方位解析 Vue 模板(<template> 部分)中的表达式、指令绑定(如 v-bind, v-on)和插值({{ }})都在一个特定的作用域内求值。这个作用域由当前 组件…...
从零开始了解数据采集(二十八)——制造业数字孪生
近年来,我国的工业领域正经历一场前所未有的数字化变革,从“双碳目标”到工业互联网平台的推广,国家政策和市场需求共同推动了制造业的升级。在这场变革中,数字孪生技术成为备受关注的关键工具,它不仅让企业“看见”设…...
ArcPy扩展模块的使用(3)
管理工程项目 arcpy.mp模块允许用户管理布局、地图、报表、文件夹连接、视图等工程项目。例如,可以更新、修复或替换图层数据源,修改图层的符号系统,甚至自动在线执行共享要托管在组织中的工程项。 以下代码展示了如何更新图层的数据源&…...
Java中栈的多种实现类详解
Java中栈的多种实现类详解:Stack、LinkedList与ArrayDeque全方位对比 前言一、Stack类——Java最早的栈实现1.1 Stack类简介1.2 常用方法1.3 优缺点分析 二、LinkedList类——灵活的双端链表2.1 LinkedList类简介2.2 常用方法2.3 优缺点分析 三、ArrayDeque类——高…...























