C++多继承
文章目录C多继承复杂菱形继承及菱形虚拟继承单继承、多继承、菱形继承菱形虚拟继承虚拟继承原理继承的总结和反思继承 vs 组合C多继承复杂菱形继承及菱形虚拟继承单继承、多继承、菱形继承单继承一个子类只有一个直接父类时称这个继承关系为单继承多继承一个子类有两个或以上直接父类时称这个继承关系为多继承classStudent{protected:int_num;};classTeacher{protected:int_id;};classAssistant:publicStudent,publicTeacher{protected:string _majorCourse;};菱形继承菱形继承是多继承的一种特殊情况。classPerson{public:string _name;};classStudent:publicPerson{protected:int_num;};classTeacher:publicPerson{protected:int_id;};classAssistant:publicStudent,publicTeacher{protected:string _majorCourse;};单继承在上一章节我们已经了解过了本章节我们详细了解一下多继承和多继承中的菱形继承。多继承我们可以认为是你父母生下了你你继承了你父母的基因菱形继承就好比你爷爷奶奶的两个孩子结婚生下了你我们知道正常非近亲结婚生子孩子一般不会出现问题的而近亲结婚生子这个孩子大概率是有问题的。而多继承中的菱形继承就相当于我们的近亲结婚生子为什么呢因为菱形继承我们的源头都是同一个那么我们在继承和静态的时候了解过static只会实例出一份来但是正常来说菱形继承的大部分数据不会是static也就是说它的所有派生类都可以去访问并修改数据那么在多继承中这份数据应该是每人独一份呢还是每人共享一份呢我们看一下下面这个代码就知道了classPerson{public:string _name;};classStudent:publicPerson{protected:int_num;};classTeacher:publicPerson{protected:int_id;};classAssistant:publicStudent,publicTeacher{protected:string _majorCourse;};intmain(){Assistant a1;// a1._name 张三; // 具有二义性不知道访问谁a1.Student::_name学生张三;//指定访问解决了二义性但是没有解决数据冗余的问题a1.Teacher::_name教师张三;couta1.Student::_name a1.Student::_nameendl;couta1.Teacher::_name a1.Teacher::_nameendl;couta1.Student::_name a1.Student::_nameendl;couta1.Teacher::_name a1.Teacher::_nameendl;}答案是独占那么这会有什么问题呢独占就像同一句话在不同场景里面表达的意思会有所不同那么这在我们生活中确实没什么太大影响但是在计算机中影响就比较大了因为它只能按语法和内存模型严格判断。独占会带来两个严重问题二义性Assistant同时继承了Student和Teacher而这两个基类又都继承自Person。因此Assistant对象里有两份Person子对象_name也就有两份。如果你直接写a1._name 张三;编译器在编译阶段就不知道你要访问的是Student路径上的_name还是Teacher路径上的_name于是直接报错。C 提供的解决办法是用作用域限定符显式调用比如a1.Student::_name 学生张三;。但这只是绕开了二义性并没有解决数据重复的问题。数据冗余通常某些冗余设计是为了提高程序的容错性或鲁棒性但是菱形继承的冗余并非有意设计而是继承关系导致的重复数据。在多继承中如果多个派生类都继承同一个基类且没有使用虚拟继承那么每个派生类都会包含一份基类子对象。继承层次越深、派生类越多最底层的派生类就会包含多份基类数据以及自身的成员造成内存膨胀管理起来也极易出错。那么该怎么解决上述问题呢我们接着来看。菱形虚拟继承虚拟继承可以解决菱形继承的二义性和数据冗余的问题。如上面的继承关系在Student和Teacher的继承Person时使用虚拟继承即可解决问题。需要注意的是虚拟继承不要在其他地方去使用。虚拟继承格式class派生类:virtual继承方式 基类{};classPerson{public:string _name;};classStudent:virtualpublicPerson{protected:int_num;};classTeacher:virtualpublicPerson{protected:int_id;};classAssistant:publicStudent,publicTeacher{protected:string _majorCourse;};voidTest(){Assistant a;a._namepeter;}虚拟继承原理那么虚拟继承是怎么解决二义性和数据冗余的呢为了便于大家的理解我们这里使用下面这个例子来演示并通过查看内存的方式来向大家展示一下虚拟继承是如何解决二义性和数据冗余的classA{public:int_a;};// class B : public AclassB:virtualpublicA{public:int_b;};// class C : public AclassC:virtualpublicA{public:int_c;};classD:publicB,publicC{public:int_d;};intmain(){D d;d.B::_a1;d.C::_a2;d._b3;d._c4;d._d5;return0;}下图是菱形继承的内存对象成员模型这里可以看到数据冗余下图是菱形虚拟继承的内存对象成员模型这里可以分析出D对象中将A放到的了对象组成的最下面这个A同时属于B和C那么B和C如何去找到公共的A呢这里是通过了B和C的两个指针指向的一张表。这两个指针叫虚基表指针这两个表叫虚基表。虚基表中存的偏移量。通过偏移量可以找到下面的A。虚拟继承解决了二义性和数据冗余根据上面的图片我们知道都是在D的内存中包含的B/C那么既然都是在D的内存里为什么B/C还要去找属于自己的A那么我们看下面这个伪代码是否能为你解惑D d;B bd;C cd;当D给B/C赋值时是不是要找出B/C成员中的A才能赋值过去是的用 D 对象给 B/C 对象赋值时需要找出 B/C 成员中的 A 才能正确赋值。为什么呢我们可以把D想象是一个大箱子里面有三个小格子B 格子、C 格子、A 格子。但 A 格子只有一个放在箱子最底下。B 格子里有一张纸条写着“A 在我下面 20 厘米”。C 格子里也有一张纸条写着“A 在我下面 10 厘米”。现在你要把 D 箱子里的 B 格子单独拿出来复制成一个独立的 B 小箱子。这个 B 小箱子必须包含一个 A 小格子因为 B 是 A 的儿子。所以你打开 B 格子看到纸条按照“下面 20 厘米”找到了大箱子底部的 A 格子把它也复制到 B 小箱子里。同理复制C格子也是一样的总结虚拟继承是为了解决菱形继承的二义性和数据冗余的它通过虚基表的方式让所有派生类能够找到源头的基类。下面是上面的Person关系菱形虚拟继承的原理解释继承的总结和反思很多人说C语法复杂其实多继承就是一个体现。有了多继承就存在菱形继承有了菱形继承就有菱形虚拟继承底层实现就很复杂。所以一般不建议设计出多继承一定不要设计出菱形继承。否则在复杂度及性能上都有问题。多继承可以认为是C的缺陷之一很多后来的OO语言都没有多继承如Java。继承 vs 组合public继承是一种is-a关系派生类对象是一个基类对象。组合是一种has-a关系B 组合了 AB 对象中有一个 A 对象。继承是白箱复用基类内部细节对子类可见破坏封装基类改变会影响派生类依赖强、耦合高。组合是黑箱复用通过组装对象获得新功能要求对象有良好接口内部细节不可见类间依赖弱、耦合低有助于保持封装。实际应尽量多用组合耦合低、易维护但适合继承的关系用继承实现多态也必须继承。能用组合就用组合。// Car和BMW Car和Benz构成is-a的关系classCar{protected:string _colour白色;// 颜色string _num陕ABIT00;// 车牌号};classBMW:publicCar{public:voidDrive(){cout好开-操控endl;}};classBenz:publicCar{public:voidDrive(){cout好坐-舒适endl;}};// Tire和car构成has-a的关系classTire{protected:string _brandMichelin;// 品牌size_t _size17;// 尺寸};classCar{protected:string _colour白色;// 颜色string _num陕ABIT00;// 车牌号Tire _t;// 轮胎};完

相关新闻

运维干货:远程备份数据库怎么搭?不暴露端口、可监控的完整方案

运维干货:远程备份数据库怎么搭?不暴露端口、可监控的完整方案

一、先明确一件事:你要备份的是"导出文件",不是"数据库目录" 讨论远程备份数据库时,不少运维容易陷入两个误区:一是直接将数据库端口映射至公网,再依靠远程连接进行拉取;二是在脚本中直…

2026/10/7 15:20:31 阅读更多 →
嵌入式显示驱动移植:MIPI-DSI Panel驱动与DRM框架实战

嵌入式显示驱动移植:MIPI-DSI Panel驱动与DRM框架实战

1. 屏幕点亮这件事,到底在折腾什么一块屏幕从“黑砖”到“出画面”,中间隔着的不是一根线,而是一整套显示子系统的协同工作。很多刚接触嵌入式显示驱动的朋友,拿到一块新屏,第一反应是“接上线不就行了”,结…

2026/10/7 15:20:31 阅读更多 →
构建边缘节点OS:内核裁剪、网络调优与缓存实战

构建边缘节点OS:内核裁剪、网络调优与缓存实战

1. cloudflare-os 是什么,以及我为什么要折腾它先说结论:cloudflare-os 并不是你跑到官网就能直接下载的发行版镜像,它更像 Cloudflare 边缘网络这座大厦的骨架。很多人一提到 Cloudflare,脑子里只有 CDN、WAF、DNS 这些产品名&am…

2026/10/7 15:20:31 阅读更多 →

最新新闻

淋巴细胞目标检测实战:从标注格式转换到YOLO训练避坑指南

淋巴细胞目标检测实战:从标注格式转换到YOLO训练避坑指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/7 16:01:28 阅读更多 →
树莓派计算模块CM4与CM5全SKU对比与选型指南

树莓派计算模块CM4与CM5全SKU对比与选型指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/7 16:01:27 阅读更多 →
SystemC与TLM2.0的ESL性能建模实战:从架构评估到GEM5联合仿真

SystemC与TLM2.0的ESL性能建模实战:从架构评估到GEM5联合仿真

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/7 16:01:27 阅读更多 →
Altium Designer PCB开窗挖槽:阻焊开窗与机械层铣槽槽孔

Altium Designer PCB开窗挖槽:阻焊开窗与机械层铣槽槽孔

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/7 16:01:27 阅读更多 →
SMB版本差异与Windows局域网共享故障排查指南

SMB版本差异与Windows局域网共享故障排查指南

简介:smb.rar_SMB 是一份以经典《超级玛丽》(Super Mario Bros)为蓝本的 2D 平台游戏源码工程,面向刚接触游戏编程的 C 语言学习者和爱好者,演示了从窗口创建、资源加载到游戏逻辑更新的完整流程。压缩包内共 33 个文件…

2026/10/7 16:01:27 阅读更多 →
PDN阻抗优化与芯片供电仿真:Sigrity+ADS双工具实战指南

PDN阻抗优化与芯片供电仿真:Sigrity+ADS双工具实战指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/7 16:00:27 阅读更多 →

日新闻

ROS2机械臂仿真与运动控制:从URDF建模到Gazebo实战全解析

ROS2机械臂仿真与运动控制:从URDF建模到Gazebo实战全解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/7 1:01:58 阅读更多 →
用浏览器直接改ESP32的WiFi密码:NVS键值配置工具设计与实现

用浏览器直接改ESP32的WiFi密码:NVS键值配置工具设计与实现

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/7 1:02:00 阅读更多 →
芯片封装缺陷检测:扫描声学显微镜(SAT)原理与实操指南

芯片封装缺陷检测:扫描声学显微镜(SAT)原理与实操指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/7 1:02:00 阅读更多 →

周新闻

KT148A语音芯片外挂8002D功放的工程实践指南

KT148A语音芯片外挂8002D功放的工程实践指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/7 14:34:12 阅读更多 →
LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/7 14:34:13 阅读更多 →
ARM架构深度解析:从RISC设计理念到交叉编译实战

ARM架构深度解析:从RISC设计理念到交叉编译实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/7 9:29:10 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/7 14:34:12 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/7 11:43:46 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/7 13:34:55 阅读更多 →