C++:多继承虚继承
在C++中,虚继承(Virtual Inheritance)是一种特殊的继承方式,用于解决菱形继承(Diamond Inheritance)问题。菱形继承指的是一个类同时继承自两个或更多个具有共同基类的类,从而导致了多个实例同一个基类的实例的冗余。
多继承-菱形继承
现在来思考以下经典的菱形继承问题:
Animal/ \cat bear\ /panda
在这个继承结构中,类 Animal 是基类,类 cat 和 bear 都直接继承自 Animal,而类 panda 继承自 cat 和 bear。当使用传统的继承方式时,panda 类将会继承两份 Animal 类的实例,这会导致冗余。
以下代码就是典型的菱形继承的例子:
class Animal
{
public:Animal();~Animal();int m_nAge;
};
class Cat : public Animal
{
public:Cat();~Cat();
};
class bear:public Animal
{
public:bear();~bear();
};
class Panda:public Cat,public bear
{
public:Panda();~Panda();
};
Animal 类:Animal 类是一个基类,具有一个 m_nAge 成员变量,用于表示动物的年龄。
Cat 类和 bear 类:Cat 类和 bear 类分别是 Animal 类的公有派生类。它们继承了 Animal 类的成员变量和方法。
Panda 类:Panda 类同时公有派生自 Cat 类和 bear 类,从而继承了这两个类的成员。由于 Cat 类和 bear 类都是从 Animal 类继承而来的,因此 Panda 类实际上包含了两份 Animal 类的成员变量 m_nAge,这导致冗余数据。
在构造函数中设置标志,创建panda对象后得到的结果:创建一个Panda对象,Animal构造了两次。

此时我在主程序中进行panda对象的创建,并尝试对panda继承下来的的m_nAge对象进行赋值:

此时程序报错,并提示Panda的m_nAge成员不明确,原因其实就是因为Panda 继承自Cat和bear两个类,那么就意味着Panda类继承了两份 Animal 类的成员变量 m_nAge,此时使用panda->m_nAge = 10;对Panda的变量进行赋值编译器就会混淆;如果不想程序爆红就在赋值时就必须成员变量的继承来源:
int main() {Panda * panda = new Panda;//成员变量的赋值panda->Cat::m_nAge = 10;panda->bear::m_nAge = 15;
std::cout << "Panda Age:" << panda->Cat::m_nAge << " Panda AgeB:" << panda->bear::m_nAge << std::endl;delete panda;system("pause");return 0;
}
panda->Cat::m_nAge = 10;:给 panda 对象中 Cat 类的成员变量 m_nAge 赋值为 10。
panda->bear::m_nAge = 15;:给 panda 对象中 bear 类的成员变量 m_nAge 赋值为 15。
就算解决了程序不报错的问题其实菱形继承(多继承)时还会出现其他问题:
1.数据冗余:每个派生类实例都会包含基类实例的副本,这可能会导致内存空间的浪费,特别是在多重继承的情况下,可能会存在多份相同的基类数据。 2.数据一致性:如果多个派生类实例共享同一个基类实例,那么当修改其中一个派生类实例中的基类数据时,会影响到其他共享同一基类实例的派生类实例,这可能会导致数据不一致的问题。 3.维护困难:当多个派生类实例共享同一个基类实例时,可能会增加代码的复杂性和维护成本,因为需要确保在任何修改基类数据的地方都能正确地处理多个派生类实例。 4.生命周期问题:如果派生类实例在不同的时间点创建和销毁,而共享的基类实例在某个派生类实例被销毁后还继续存在,这可能会导致悬挂指针或内存泄漏等问题
这个时候就可以使用虚继承对以上问题进行统一解决;
虚继承
虚继承通过使用关键字 virtual 来解决这个问题。当一个类以虚继承方式继承自一个基类时,无论该类被多次继承,其基类的实例只会在继承层次结构中的最顶层被创建一次。这意味着,对于上面的菱形继承问题,使用虚继承后,D 类将只继承一份 A 类的实例。
回到上述例子:
class Animal
{
public:Animal();~Animal();
int m_nAge;
}
//使用虚继承
class Cat : public virtual Animal
{
public:Cat();~Cat();
};
//使用虚继承
class bear:public virtual Animal
{
public:bear();~bear();
};
class Panda:public Cat,public bear
{
public:Panda();~Panda();
};
Cat 类和 bear 类:这两个类都使用了虚继承,即使用 virtual 关键字来继承自 Animal 类。这意味着无论 Cat 类和 bear 类被多次继承,Animal 类的实例都只会在继承层次结构中的最顶层被创建一次。这样可以避免在 Panda 类中出现多个 Animal 类的实例,从而解决了菱形继承问题。
Panda 类:Panda 类同时公有派生自 Cat 类和 bear 类,从而继承了这两个类的成员。因为 Cat 类和 bear 类都是虚继承自 Animal 类的,所以 Panda 类中只包含了一个 Animal 类的实例,从而避免了多个实例共享同一个基类实例的冗余问题。
这就意味着此时我们在主函数中创建panda对象,并对对象的m_nAge成员进行赋值/访问:
int main() {Panda * panda = new Panda;panda->m_nAge = 10;std::cout << "Panda Age:" << panda->m_nAge << std::endl;delete panda;
}
运行结果:
Panda Age:10
panda对象中的m_nAge成员变量就只有一个副本,这个时候就对对象中的成员进行访问时就无需再指定继承路径了。
相关文章:
C++:多继承虚继承
在C中,虚继承(Virtual Inheritance)是一种特殊的继承方式,用于解决菱形继承(Diamond Inheritance)问题。菱形继承指的是一个类同时继承自两个或更多个具有共同基类的类,从而导致了多个实例同一个…...
Linux进程间通信
每个进程的用户空间都是独立的,不能相互访问。 所有进程的内核空间(32位系统3G-4G)都是共享的 应用场景 作为缓冲区,处理速度不同的进程之间的数据传输资源共享:多个进程之间共享同样的资源,一个进程对共享数据的修改,…...
【二叉树算法题记录】222. 完全二叉树的节点个数
题目描述 给你一棵 完全二叉树 的根节点root ,求出该树的节点个数。 完全二叉树的定义如下:在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位…...
每日新闻掌握【2024年5月6日 星期一】
2024年5月06日 星期一 农历三月廿八 大公司/大事件 多个品牌黄金优惠后价格重回600元/克以下 “五一”假期期间,记者走访调研黄金消费市场发现,受国际金价回落及“五一”假期促销等多重因素影响,终端黄金价格出现了较为明显的回落。包括周大…...
谈谈Tcpserver开启多线程并发处理遇到的问题!
最近在学习最基础的socket网络编程,在Tcpserver开启多线程并发处理时遇到了一些问题! 说明 在linux以及Windows的共享文件夹进行编写的,所以代码中有的部分使用 #ifdef WIN64 ... #else ... #endif 进入正题!!&…...
618好物节不知道买什么?快收下这份好物推荐指南!
随着618好物节的临近,你是否在为选择什么产品而犹豫不决?不用担忧,我精心准备了一份购物指南,旨在帮助你发现那些性价比高、口碑爆棚的商品。无论是科技新品还是生活小物件,这份指南都能帮你快速定位到那些值得投资的好…...
Django高级表单处理与验证实战
title: Django高级表单处理与验证实战 date: 2024/5/6 20:47:15 updated: 2024/5/6 20:47:15 categories: 后端开发 tags: Django表单验证逻辑模板渲染安全措施表单测试重定向管理最佳实践 引言: 在Web应用开发中,表单是用户与应用之间进行交互的重要…...
类和对象-Python-第一部分
初识对象 使用对象组织数据 class Student:nameNonegenderNonenationalityNonenative_placeNoneageNonestu_1Student()stu_1.name"林军杰" stu_1.gender"男" stu_1.nationality"中国" stu_1.native_place"山东" stu_1.age31print(stu…...
Pytorch实现图片异常检测
图片异常检测 异常检测指的是在正常的图片中找到异常的数据,由于无法通过规则进行识别判断,这样的应用场景通常都是需要人工进行识别,比如残次品的识别,图片异常识别模型的目标是可以代替或者辅助人工进行识别异常图片。 AnoGAN…...
【NOI-题解】1586. 扫地机器人1430 - 迷宫出口1434. 数池塘(四方向)1435. 数池塘(八方向)
文章目录 一、前言二、问题问题:1586 - 扫地机器人问题:1430 - 迷宫出口问题:1434. 数池塘(四方向)问题:1435. 数池塘(八方向) 三、感谢 一、前言 本章节主要对深搜基础题目进行讲解…...
探究MySQL行格式:解析DYNAMIC与COMPACT的异同
在MySQL中,行格式对于数据存储和检索起着至关重要的作用。MySQL提供了多种行格式,其中DYNAMIC和COMPACT是两种常见的行格式。 本文将深入探讨MySQL行格式DYNAMIC和COMPACT的区别,帮助读者更好地理解它们的特点和适用场景。 1. MySQL行格式简…...
MATLAB绘制蒸汽压力和温度曲线
蒸汽压力与温度之间的具体关系公式一般采用安托因方程(Antoine Equation),用于描述纯物质的蒸汽压与温度之间的关系。安托因方程的一般形式如下: [\log_{10} P A - \frac{B}{C T}] 其中, (P) 是蒸汽压(…...
repo跟git的关系
关于repo 大都讲的太复杂了,大多是从定义角度跟命令角度去讲解,其实从现实项目使用角度而言repo很好理解. 我们都知道git是用来管理项目的,多人开发过程中git功能很好用.现在我们知道一个项目会用一个git仓库去管理,项目的开发过程中会使用git创建分支之类的来更好的维护项目代…...
Mysql 8.0 -- 最新版本安装(保姆级教程)
Mysql 8.0 -- 最新版本安装(保姆级教程) 一,下载Mysql数据库: 官网链接:https://www.mysql.com/downloads/ 二,安装Mysql: 三,找到Mysql安装目录: 找到mysql安装目录…...
sql优化思路
sql的优化经验 这里解释一下SQL语句的优化的原理 1.指明字段名称,可以尽量使用覆盖索引,避免回表查询,因此可以提高效率 2.字面意思,无需过多赘述。索引就是为了提高查询效率的。 3.图中两条sql直接可以使用union all 或者 uni…...
gin学习1-7
package mainimport ("github.com/gin-gonic/gin""net/http" )// 响应json还有其他响应差不多可以去学 func _string(c *gin.Context) {c.String(http.StatusOK, "lalal") } func _json(c *gin.Context) {//json响应结构体type UsetInfo struct …...
likeshop多商户单商户商城_likeshop跑腿源码_likeshop物品租赁系统开源版怎么配置小程序对接?
本人是商业用户所以能持续得到最新商业版,今天我说下likeshop里面怎么打包小程序,大家得到程序时候会发现它有admin目录 app目录 server目录 这三个目录分别是做什么呢? 1.admin目录 下面都是架构文件使用得是Node.js打包得,至于…...
(done) LSTM 详解 (包括它为什么能缓解梯度消失)
RNN 参考视频:https://www.bilibili.com/video/BV1e5411K7oW/?p2&spm_id_frompageDriver&vd_source7a1a0bc74158c6993c7355c5490fc600 LSTM 参考视频:https://www.bilibili.com/video/BV1qM4y1M7Nv?p5&vd_source7a1a0bc74158c6993c7355c5…...
springboot使用研究
map-underscore-to-camel-case: true 开启驼峰命名 GetMapping("/userInfo")public Result<Users> userInfo(RequestHeader(name "Authorization") String token,HttpServletResponse response) {Map<String, Object> map JwtUtil.parseT…...
老旧房屋用电线路故障引起的电气火灾预防对策
摘 要:在我国新农村建设方针指引下,农村地区的发展水平有了显著提高。在农村经济发展中,我们也要认识到其中存在的风险隐患问题,其中重要的就是火灾事故。火灾事故给农村发展带来的不利影响,不仅严重威胁到农村群众的生…...
量子测量诱导相变在玻色系统中的实验实现
1. 量子测量诱导相变的理论基础量子测量诱导相变(Measurement-Induced Phase Transition, MIPT)是近年来量子多体物理领域的重要发现。这种相变不同于传统热力学相变,它完全由量子测量操作与酉演化之间的动态竞争所驱动。在玻色系统中&#x…...
实时代码光标同步工具:跨设备与团队协作的开发效率利器
1. 项目概述:一个为开发者设计的代码光标同步工具如果你和我一样,经常需要在多台设备、多个编辑器窗口,甚至是与同事进行远程结对编程时,保持代码编辑位置的同步,那么你肯定理解那种来回切换、手动寻找上次编辑位置的痛…...
ADAS环视系统与视频解码器关键技术解析
1. ADAS环视系统技术解析1.1 汽车安全技术演进路径从ABS防抱死系统到安全气囊,再到如今的ADAS(高级驾驶辅助系统),汽车安全技术在过去二十年经历了三次重大迭代。德国车企在这个领域始终保持着技术领先,最早实现了车道…...
从-15dBm到+16dBm:STC8G信标FM射频放大链路实测与优化
1. 从零开始的FM信标信号放大实战 去年我在做一个野外定位项目时,遇到了一个棘手的问题:用STC8G微控制器生成的FM信标信号,在空旷地带的有效传输距离还不到50米。当时测得的初始输出功率只有-15dBm左右,这个强度连穿过一片小树林都…...
AI编程实战:从Prompt工程到工作流集成的CRISP框架与避坑指南
1. 项目概述:从“AI编码101”看个人技术栈的构建与沉淀最近在GitHub上看到一个挺有意思的项目,叫jnMetaCode/ai-coding-101。光看这个名字,你可能会觉得这又是一个关于如何使用AI写代码的入门教程合集。但作为一个在技术一线摸爬滚打了十多年…...
ThunderAI:用大语言模型插件打造智能邮件工作流
1. 项目概述:当AI助手遇见邮件客户端 如果你和我一样,每天要在Thunderbird里处理几十甚至上百封邮件,那你肯定也经历过那种“邮件疲劳”——写回复时词穷、面对长篇大论需要快速提炼要点、或者想给邮件分个类却懒得手动打标签。传统的邮件客…...
2026年小程序多少钱对比:精选5大权威推荐帮你选对平台
小程序开发方案的选择直接影响功能匹配度与成本效益,2026年主流服务商主要分为模板化与定制化两类路径。本文将从开发费用构成、五大平台核心方案及选择策略三方面展开分析,帮助您快速定位适合自身业务阶段与预算的选项。内容涵盖基础功能解析、价格对比…...
Logseq AI助手插件:在知识管理笔记中集成ChatGPT智能写作与编辑
1. 项目概述:在Logseq中引入你的AI副驾驶 如果你和我一样,是个重度依赖Logseq来构建个人知识库的笔记爱好者,同时又对AI辅助写作和思考的潜力充满好奇,那么你肯定不止一次想过:要是能把ChatGPT的能力无缝集成到Logseq…...
LinkSwift:九大网盘直链解析工具使用指南
LinkSwift:九大网盘直链解析工具使用指南 【免费下载链接】Online-disk-direct-link-download-assistant 一个基于 JavaScript 的网盘文件下载地址获取工具。基于【网盘直链下载助手】修改 ,支持 百度网盘 / 阿里云盘 / 中国移动云盘 / 天翼云盘 / 迅雷云…...
OpenClaw插件实战:为Telegram审批消息添加一键操作按钮
1. 项目概述:为OpenClaw的Telegram频道添加一键审批按钮如果你正在使用OpenClaw,并且像我一样,把Telegram作为主要的交互和通知渠道,那你肯定对下面这个场景不陌生:AI助手在执行某个需要授权的命令(比如exe…...
