C++:菱形继承与菱形虚拟继承

一、菱形继承

单继承:一个子类只有一个直接父类时称这个继承关系为单继承

多继承:一个子类有两个或以上直接父类时称这个继承关系为多继承

菱形继承:菱形继承是多继承的一种特殊情况,派生类继承自两个间接基类,而这两个间接基类又继承自同一个基类,形成了一个菱形的继承关系。具体来说,就是两个子类继承同一个父类,而又有子类同时继承这两个子类。 

菱形继承的问题:从下面的对象成员模型构造,可以看出菱形继承有数据冗余和二义性的问题。 在Assistant的对象中Person成员会有两份

class Person
{
public:string _name; // 姓名
};
class Student : public Person
{
protected:int _num; //学号
};
class Teacher : 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";
}

 虚拟继承可以解决菱形继承的二义性和数据冗余的问题。如上面的继承关系,在Student和 Teacher的继承Person时使用虚拟继承,即可解决问题。

二、菱形虚拟继承

为了研究虚拟继承原理,我们给出了一个简化的菱形继承继承体系,再借助内存窗口观察对象成 员的模型。

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;
};
int main()
{D d;d.B::_a = 1;d.C::_a = 2;d._b = 3;d._c = 4;d._d = 5;return 0;
}

由菱形继承的内存对象成员模型可以看到数据冗余。

菱形虚拟继承的关键字virtual需要加在基类的继承声明中,用于指定某个基类是以虚拟的方式被继承的,通常是将共享的基类(即菱形顶部的基类)声明为虚拟继承。

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;
};
int main()
{D d;d.B::_a = 1;d.C::_a = 2;d._b = 3;d._c = 4;d._d = 5;return 0;
}

下图是菱形虚拟继承的内存对象成员模型:这里可以分析出D对象中将A放到的了对象组成的最下 面,这个A同时属于B和C,那么B和C如何去找到公共的A呢?这里是通过了B和C的两个指针,指 向的一张表。这两个指针叫虚基表指针,这两个表叫虚基表。虚基表中存的偏移量。通过偏移量 可以找到下面的A。 

// 为什么D中B和C部分要去找属于自己的A?那么大家看看当下面的赋值发生时,d是
不是要去找出B/C成员中的A才能赋值过去?
D d;
B b = d;
C c = d;

下面是上面的Person关系菱形虚拟继承的原理解释: 

 三、继承的总结和反思

1. 有了多继承,就存在菱形继承,有了菱 形继承就有菱形虚拟继承,底层实现就很复杂。所以一般不建议设计出多继承,一定不要设 计出菱形继承。否则在复杂度及性能上都有问题。

2. 继承和组合:

  • public继承是一种is-a的关系。也就是说每个派生类对象都是一个基类对象。
  • 组合是一种has-a的关系。假设B组合了A,每个B对象中都有一个A对象。
  • 优先使用对象组合,而不是类继承 。
  • 继承允许你根据基类的实现来定义派生类的实现。这种通过生成派生类的复用通常被称为白箱复用(white-box reuse)。术语“白箱”是相对可视性而言:在继承方式中,基类的内部细节对子类可见 。继承一定程度破坏了基类的封装,基类的改变,对派生类有很大的影响。派生类和基类间的依赖关系很强,耦合度高。
  • 对象组合是类继承之外的另一种复用选择。新的更复杂的功能可以通过组装或组合对象来获得。对象组合要求被组合的对象具有良好定义的接口。这种复用风格被称为黑箱复用(black-box reuse),因为对象的内部细节是不可见的。对象只以“黑箱”的形式出现。组合类之间没有很强的依赖关系,耦合度低。优先使用对象组合有助于你保持每个类被封装。
  • 实际尽量多去用组合。组合的耦合度低,代码维护性好。不过继承也有用武之地的,有 些关系就适合继承那就用继承,另外要实现多态,也必须要继承。类之间的关系可以用继承,可以用组合,就用组合。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/678865.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java--io流(一)

1. 前置知识 字符集是什么? 字符集(Character Set)是一组字符的集合,它定义了可以在计算机系统中使用的所有字符。字符集可以包括字母、数字、标点符号、控制字符、图形符号等。字符集使得计算机能够存储、处理和显示各种语言和…

理解DPI:从数码到打印的深入分析

目录标题 1. DPI的定义2. DPI与图像质量2.1. 对于打印来说:2.2. 对于屏幕显示来说: 3. 如何计算DPI4. 调整DPI4.1. 提高DPI:4.2. 降低DPI: 5. DPI与图像文件大小的关系6. 实际应用中的DPI6.1. 专业打印:6.2. 屏幕设计&…

如何在Ubuntu系统上定制文件系统

基于全志T507H处理器设计研发的OKT507-C开发板为例进行介绍。 Forlinx Desktop(Ubuntu)系统基于Ubuntu官方为嵌入式设备制作的操作系统-Lubuntu,该操作系统具备apt-get、ldd等常用的命令,若需要安装软件则直接apt-get在线安装即可,不需进行交…

DDPM与扩散模型

很早之前就新建了一个专栏从0开始弃坑扩散模型 ,但发了一篇文章就没有继续这一系列,在这个AIGC的时代,于是我准备重启这个专栏。 整个专栏的学习顺序可以见这篇汇总文章 这是本专栏的第一章 目录 引言生成模型的发展历程 引言 扩散模型( Diffusion Mode…

数据结构-线性表-链表-2.3-6

有一个带头结点的单链表L&#xff0c;设计一个算法使其元素递增有序。 void sort(Linklist &L){LNode *pL->next,*pre;LNode *rp->next;p->nextNULL;pr;while(p){rp->next;preL;while(pre->next!NULL&&pre->next->data<p->data){prepre…

ACM实训冲刺第一天

目录 ACM实训课程考核 考核内容 备赛安排 推荐学习资源 ACM实训准备规划 前话 历届习题&#xff08;未曾改变&#xff09; 第0套 第1套 第2套 第3套 第4套 规划 5.8 - 5.12 &#xff08;11周&#xff09; 5.13-5.19&#xff08;12周&#xff09; 5.20-5.26&…

【计算机毕业设计】基于SSM++jsp的菜匣子优选系统【源码+lw+部署文档+讲解】

目录 第一章 绪 论 第二章 关键技术的研究 2.1 JSP技术介绍 2.2 JAVA简介 2.3 ECLIPSE 开发环境 2.4 Tomcat服务器 2.5 MySQL数据库 第三章 系统分析 3.1 系统设计目标 3.2 系统可行性分析 3.3 系统功能分析和描述 3.4系统UML用例分析 3.4.1管理员用例 3.4.2用户用例 3.5系统流…

远动通讯屏的作用

远动通讯屏的作用 远动通讯屏有时有称为调度数据网柜&#xff0c;远动通讯屏具体干啥作用&#xff1f;远动通讯屏是以计算机为基础的生产过程与调度自动化系统&#xff0c;可以对现场的运行设备进行监视和控制、以实现数据采集、设备测量、参数调节以及各类信号报警等各项功能。…

【Android】源码解析Activity的结构分析

源码解析Activity的结构分析 目录 1、Activity、View、Window有什么关联&#xff1f;2、Activity的结构构建流程3 源码解析Activity的构成 3.1 Activity的Attach方法3.2 Activity的OnCreate 4、WindowManager与View的关系总结 1、一个Activity对应几个WindowManage&#xff0…

软考143-下午题-【试题二】:E-R图、关系模式

一、分值与目标 15分&#xff0c;目标10 二、题目形式 示例&#xff1a; 三、E-R图的基本图形元素 示例&#xff1a; 3-1、实体 1、弱实体 在现实世界中有一种特殊的联系&#xff0c;这种联系代表实体间的所有 (Ownership) 关系&#xff0c;例如&#xff1a;职工与家属的联系…

Tuxera NTFS for Mac Mac用户无缝地读写NTFS格式的硬盘和U盘

在数字化时代&#xff0c;数据交换和共享变得日益重要。然而&#xff0c;对于Mac用户来说&#xff0c;与Windows系统之间的文件交换可能会遇到一些挑战。这是因为Mac OS默认不支持Windows常用的NTFS文件系统。幸运的是&#xff0c;Tuxera NTFS for Mac为我们提供了一个优雅的解…

使用电路仿真软件教学的优势分析

随着科技的飞速发展&#xff0c;电子工程领域对人才的需求与日俱增。为了满足这一需求&#xff0c;教育者们不断探索着更加高效、直观的教学方法。电路仿真软件的出现&#xff0c;为电子工程教学注入了新的活力&#xff0c;它以其独特的优势&#xff0c;成为现代电子工程教育中…