当前位置: 首页 > news >正文

C++:多继承虚继承

在C++中,虚继承(Virtual Inheritance)是一种特殊的继承方式,用于解决菱形继承(Diamond Inheritance)问题。菱形继承指的是一个类同时继承自两个或更多个具有共同基类的类,从而导致了多个实例同一个基类的实例的冗余。

多继承-菱形继承

现在来思考以下经典的菱形继承问题:

     Animal/ \cat  bear\ /panda

在这个继承结构中,类 Animal 是基类,类 catbear 都直接继承自 Animal,而类 panda 继承自 catbear。当使用传统的继承方式时,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();
};

AnimalAnimal 类是一个基类,具有一个 m_nAge 成员变量,用于表示动物的年龄。

Cat 类和 bearCat 类和 bear 类分别是 Animal 类的公有派生类。它们继承了 Animal 类的成员变量和方法。

PandaPanda 类同时公有派生自 Cat 类和 bear 类,从而继承了这两个类的成员。由于 Cat 类和 bear 类都是从 Animal 类继承而来的,因此 Panda 类实际上包含了两份 Animal 类的成员变量 m_nAge,这导致冗余数据。

在构造函数中设置标志,创建panda对象后得到的结果:创建一个Panda对象,Animal构造了两次。

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

此时程序报错,并提示Pandam_nAge成员不明确,原因其实就是因为Panda 继承自Catbear两个类,那么就意味着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 类的实例,从而解决了菱形继承问题。

PandaPanda 类同时公有派生自 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中&#xff0c;虚继承&#xff08;Virtual Inheritance&#xff09;是一种特殊的继承方式&#xff0c;用于解决菱形继承&#xff08;Diamond Inheritance&#xff09;问题。菱形继承指的是一个类同时继承自两个或更多个具有共同基类的类&#xff0c;从而导致了多个实例同一个…...

Linux进程间通信

每个进程的用户空间都是独立的&#xff0c;不能相互访问。 所有进程的内核空间(32位系统3G-4G)都是共享的 应用场景 作为缓冲区&#xff0c;处理速度不同的进程之间的数据传输资源共享&#xff1a;多个进程之间共享同样的资源&#xff0c;一个进程对共享数据的修改&#xff0c…...

【二叉树算法题记录】222. 完全二叉树的节点个数

题目描述 给你一棵 完全二叉树 的根节点root &#xff0c;求出该树的节点个数。 完全二叉树的定义如下&#xff1a;在完全二叉树中&#xff0c;除了最底层节点可能没填满外&#xff0c;其余每层节点数都达到最大值&#xff0c;并且最下面一层的节点都集中在该层最左边的若干位…...

每日新闻掌握【2024年5月6日 星期一】

2024年5月06日 星期一 农历三月廿八 大公司/大事件 多个品牌黄金优惠后价格重回600元/克以下 “五一”假期期间&#xff0c;记者走访调研黄金消费市场发现&#xff0c;受国际金价回落及“五一”假期促销等多重因素影响&#xff0c;终端黄金价格出现了较为明显的回落。包括周大…...

谈谈Tcpserver开启多线程并发处理遇到的问题!

最近在学习最基础的socket网络编程&#xff0c;在Tcpserver开启多线程并发处理时遇到了一些问题&#xff01; 说明 在linux以及Windows的共享文件夹进行编写的&#xff0c;所以代码中有的部分使用 #ifdef WIN64 ... #else ... #endif 进入正题&#xff01;&#xff01;&…...

618好物节不知道买什么?快收下这份好物推荐指南!

随着618好物节的临近&#xff0c;你是否在为选择什么产品而犹豫不决&#xff1f;不用担忧&#xff0c;我精心准备了一份购物指南&#xff0c;旨在帮助你发现那些性价比高、口碑爆棚的商品。无论是科技新品还是生活小物件&#xff0c;这份指南都能帮你快速定位到那些值得投资的好…...

Django高级表单处理与验证实战

title: Django高级表单处理与验证实战 date: 2024/5/6 20:47:15 updated: 2024/5/6 20:47:15 categories: 后端开发 tags: Django表单验证逻辑模板渲染安全措施表单测试重定向管理最佳实践 引言&#xff1a; 在Web应用开发中&#xff0c;表单是用户与应用之间进行交互的重要…...

类和对象-Python-第一部分

初识对象 使用对象组织数据 class Student:nameNonegenderNonenationalityNonenative_placeNoneageNonestu_1Student()stu_1.name"林军杰" stu_1.gender"男" stu_1.nationality"中国" stu_1.native_place"山东" stu_1.age31print(stu…...

Pytorch实现图片异常检测

图片异常检测 异常检测指的是在正常的图片中找到异常的数据&#xff0c;由于无法通过规则进行识别判断&#xff0c;这样的应用场景通常都是需要人工进行识别&#xff0c;比如残次品的识别&#xff0c;图片异常识别模型的目标是可以代替或者辅助人工进行识别异常图片。 AnoGAN…...

【NOI-题解】1586. 扫地机器人1430 - 迷宫出口1434. 数池塘(四方向)1435. 数池塘(八方向)

文章目录 一、前言二、问题问题&#xff1a;1586 - 扫地机器人问题&#xff1a;1430 - 迷宫出口问题&#xff1a;1434. 数池塘&#xff08;四方向&#xff09;问题&#xff1a;1435. 数池塘&#xff08;八方向&#xff09; 三、感谢 一、前言 本章节主要对深搜基础题目进行讲解…...

探究MySQL行格式:解析DYNAMIC与COMPACT的异同

在MySQL中&#xff0c;行格式对于数据存储和检索起着至关重要的作用。MySQL提供了多种行格式&#xff0c;其中DYNAMIC和COMPACT是两种常见的行格式。 本文将深入探讨MySQL行格式DYNAMIC和COMPACT的区别&#xff0c;帮助读者更好地理解它们的特点和适用场景。 1. MySQL行格式简…...

MATLAB绘制蒸汽压力和温度曲线

蒸汽压力与温度之间的具体关系公式一般采用安托因方程&#xff08;Antoine Equation&#xff09;&#xff0c;用于描述纯物质的蒸汽压与温度之间的关系。安托因方程的一般形式如下&#xff1a; [\log_{10} P A - \frac{B}{C T}] 其中&#xff0c; (P) 是蒸汽压&#xff08…...

repo跟git的关系

关于repo 大都讲的太复杂了,大多是从定义角度跟命令角度去讲解,其实从现实项目使用角度而言repo很好理解. 我们都知道git是用来管理项目的,多人开发过程中git功能很好用.现在我们知道一个项目会用一个git仓库去管理,项目的开发过程中会使用git创建分支之类的来更好的维护项目代…...

Mysql 8.0 -- 最新版本安装(保姆级教程)

Mysql 8.0 -- 最新版本安装&#xff08;保姆级教程&#xff09; ​​ 一&#xff0c;下载Mysql数据库&#xff1a; 官网链接&#xff1a;https://www.mysql.com/downloads/ 二&#xff0c;安装Mysql: 三&#xff0c;找到Mysql安装目录&#xff1a; 找到mysql安装目录&#xf…...

sql优化思路

sql的优化经验 这里解释一下SQL语句的优化的原理 1.指明字段名称&#xff0c;可以尽量使用覆盖索引&#xff0c;避免回表查询&#xff0c;因此可以提高效率 2.字面意思&#xff0c;无需过多赘述。索引就是为了提高查询效率的。 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物品租赁系统开源版怎么配置小程序对接?

本人是商业用户所以能持续得到最新商业版&#xff0c;今天我说下likeshop里面怎么打包小程序&#xff0c;大家得到程序时候会发现它有admin目录 app目录 server目录 这三个目录分别是做什么呢&#xff1f; 1.admin目录 下面都是架构文件使用得是Node.js打包得&#xff0c;至于…...

(done) LSTM 详解 (包括它为什么能缓解梯度消失)

RNN 参考视频&#xff1a;https://www.bilibili.com/video/BV1e5411K7oW/?p2&spm_id_frompageDriver&vd_source7a1a0bc74158c6993c7355c5490fc600 LSTM 参考视频&#xff1a;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…...

老旧房屋用电线路故障引起的电气火灾预防对策​

摘 要&#xff1a;在我国新农村建设方针指引下&#xff0c;农村地区的发展水平有了显著提高。在农村经济发展中&#xff0c;我们也要认识到其中存在的风险隐患问题&#xff0c;其中重要的就是火灾事故。火灾事故给农村发展带来的不利影响&#xff0c;不仅严重威胁到农村群众的生…...

pdf2htmlEX色彩管理专家指南:高级色彩校准技术

pdf2htmlEX色彩管理专家指南&#xff1a;高级色彩校准技术 【免费下载链接】pdf2htmlEX Convert PDF to HTML without losing text or format. 项目地址: https://gitcode.com/gh_mirrors/pd/pdf2htmlEX 想要将PDF转换为HTML时保持完美的色彩还原吗&#xff1f;pdf2html…...

OpenClaw 配置目录

OpenClaw&#xff08;也称 Clawdbot&#xff09;的所有配置、状态数据、工作区和技能均集中在用户主目录下的 ~/.openclaw/&#xff08;Linux/macOS&#xff09;或 %USERPROFILE%\.openclaw\&#xff08;Windows&#xff09;这个核心目录中。 ~/.openclaw/ 是整个系统的根配置…...

OpenClaw配置文件详解:Qwen3.5-4B-Claude-4.6-Opus-Reasoning-Distilled-GGUF性能调优全参数解析

OpenClaw配置文件详解&#xff1a;Qwen3.5-4B-Claude-4.6-Opus-Reasoning-Distilled-GGUF性能调优全参数解析 1. 为什么需要手动调优OpenClaw配置 第一次看到OpenClaw的配置文件时&#xff0c;我和大多数开发者一样&#xff0c;直接选择了默认的QuickStart模式。直到某个深夜…...

Nacos如何开启ssl(https)[图文版]

首先,你得有个域名,只有域名才能有ssl 在你的腾讯云或者阿里云控制台把域名解析到nacos所在的ip上面 等待几分钟,打开cmd, ping 刚才的域名,如果返回的是nacos的ip那说明解析成功了 例如你的域名是 ttvv.com 那就 ping ttvv.com 准备证书文件 你的证书通常是 .pem 和 .key …...

PCIe Gen4眼图测试实战:如何用示波器快速定位信号完整性问题(附避坑指南)

PCIe Gen4眼图测试实战&#xff1a;示波器操作与信号完整性诊断全解析 当PCIe Gen4的信号速率突破16GT/s大关时&#xff0c;硬件工程师的工作台上总少不了一台高性能示波器。记得去年参与某企业级SSD项目时&#xff0c;我们团队连续三周被一个诡异的眼图闭合问题困扰——每次系…...

ChatTTS 自定义样本实战:如何高效构建个性化语音合成模型

最近在做一个需要个性化语音合成的项目&#xff0c;用到了ChatTTS。说实话&#xff0c;直接拿官方流程走自定义样本训练&#xff0c;那个效率真是让人有点头疼。数据准备繁琐&#xff0c;训练时间长&#xff0c;出来的效果还不一定稳定。经过一番折腾和优化&#xff0c;总算总结…...

嵌入式系统程序运行机制与存储器优化

嵌入式系统程序运行机制深度解析1. 程序运行基础架构1.1 冯诺依曼体系结构现代计算机系统&#xff08;包括嵌入式设备&#xff09;都基于冯诺依曼模型构建&#xff0c;该模型包含五个核心组件&#xff1a;运算器(ALU)&#xff1a;执行算术和逻辑运算控制器(CU)&#xff1a;协调…...

从外包到阿里P8:我的“野路子”晋升攻略

一、起点&#xff1a;外包测试员的困境与觉醒初入职场时&#xff0c;我是一名普通的外包功能测试员&#xff0c;每日重复着“点点点”的基础工作。外包身份的局限性逐渐显现&#xff1a;接触不到核心业务逻辑&#xff0c;缺乏技术成长空间&#xff0c;职业路径模糊。一次线上重…...

在LubanCat RK3568上跑通YOLOv5:手把手教你用RKNN-Toolkit-lite2部署目标检测模型

在LubanCat RK3568上部署YOLOv5模型的完整实战指南 1. 边缘计算与目标检测的完美结合 当计算机视觉遇上边缘计算&#xff0c;一场效率革命正在发生。想象一下&#xff0c;在工厂流水线上实时检测产品缺陷&#xff0c;在智慧农场中自动识别病虫害&#xff0c;或是在安防场景下即…...

Docker 学习之路-从入门到放弃-Jenkins:4

Jenkins 打开 ✅ 如图已经完全成功安装并初始化Jenkins了&#xff01;从图1可以确认&#xff1a;能正常访问Jenkins Web管理界面、登录成功核心功能入口&#xff08;Create a job/Manage Jenkins等&#xff09;正常显示构建执行器&#xff08;Build Executor Status&#xff09…...