
8-5:C++继承之多继承,菱形继承,虚继承,虚基表,继承和组合
由于在现实生活中,一个人可能会有双重角色。比如研究生可以作为助教,一方面它是学生一方面它是老师,这样一来,一个子类就有两个及以上的直接父类了,称这种继承为多继承
这种继承关系会引发数据冗余和数据二义性的问题
先不要管那多出的八个字节,其余继承关系如下
可以看出上面的a=1是公共的,b和c都继承了a,那么在赋值时d是如何找到这个位于下方的公共的a呢?上面多出的
发布日期:2021-05-06 07:22:46
浏览次数:39
分类:精选文章
本文共 2020 字,大约阅读时间需要 6 分钟。
文章目录
一:菱形继承与菱形虚拟继承
(1)多继承
之前我们所讲得继承全部属于单继承:一个子类只有一个直接父类


(2)菱形继承
C++有很多让人觉得不满意的地方,其中有一个地方就是多继承带来的菱形继承问题,抽象来看,继承关系呈现一种环形结构
如下,一个助教可以是老师也可以是学生,老师和学生同时又是人


- 数据冗余:助教里面Person会被继承两次
- 数据二义:助教的姓名到底应该是哪一个(虽然现实生活中会存在这种起别名的现象,但是我们考虑的是如身份证那样不可二义的对象)
如下代码反应的就是上述继承关系,最终编译器报错:对于name
不明确
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 _course;//主讲课程};int main(){ Assistant a; a._name = "xiaowang";}
- 上面体现的二义的问题,这个问题当然可以通过加入域作用限制符指定父类解决,但是仍然无法解决属于冗余的问题
(3)虚继承
A:如何解决
如果解决上面的问题就要使用虚继承,只需使用关键字virtual
,在下面的位置加入即可

class Student : virtual public Person{ protected: int _num;//学号};class Teacher : virtual public Person{ protected: int _id;//工号};
B:解决原理
为了方便描述,使用下面的代码作说明
class A{ public: int _a;};class B : public A{ public: int _b;};class C : 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它的所占的空间就是20个字节。将上述继承改为虚继承,那么它的大小应该变为16个字节,因为只保存了一份a,但是实际查看内存窗口发现它竟然占用了24个字节


0055db40
和0055db48
很明显是两个指针,称其为虚基表指针,他们分别指向了虚基表,虚基表中存储的是一个偏移量,通过偏移量可以找到a 
D dB b=dC c=d
d.B::a=1
这样的操作就是通过偏移量完成的 二:继承总结
(1)继承缺陷
有了多继承,就会出现菱形继承,有了菱形继承就有虚拟继承,因此底层的实现一定会很复杂。所以设计时不建议设计多继承,而且一定不能有菱形继承,否则会出现这样那样的问题
(2)继承与组合
继承class A{ };class B : public A{ }组合class A{ };class B{ A a;}
public
继承是一种is-a
的关系,也就是每个子类对象都是一个父类对象(学生也是人),而组合是一种has-a
的关系
继承体现的是白箱复用,组合体现的是黑箱复用

- 继承允许你根据父类的实现来定义子类的实现。这种方式就是白箱复用,在继承方式中,父类的内部细节对子类可见。继承一定程度上破坏了父类的封装,父类的改变对子类有很大的影响——耦合性太强
- 组合是继承外的另一种很好的选择,新的更复杂的功能可以通过组合对象获得。对象组合要求被组合的对象具有良好定义的接口,对象的内部细节对“父类”是不可见的,组合类之间没有很强的依赖性——高内聚,低耦合
设计时要优先使用组合而不是继承
- 看他们更符合
is-a
关系(比如猫是动物,狗是动物)还是has-a
关系(往往是某个对象的属性)
发表评论
最新留言
第一次来,支持一个
[***.219.124.196]2025年03月18日 23时47分45秒
关于作者

喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
《Unity3D/2D游戏开发从0到1(第二版本)》 书稿完结总结
2021-05-08
sctf_2019_easy_heap
2021-05-09
Eclipse 创建 Maven 项目
2021-05-09
input[file]标签的accept=”image/*”属性响应很慢的解决办法
2021-05-09
AT 杂题泛做
2021-05-09
StringBuilder拼接字符串,“,”在前还是在后问题
2021-05-09
给asterisk1.8.7添加menuselct选项
2021-05-09
组合模式
2021-05-09
PyQt5之音乐播放器
2021-05-09
css居中方法与双飞翼布局
2021-05-09
Redis进阶实践之十八 使用管道模式提高Redis查询的速度
2021-05-09
多指灵巧手MoveIt!与Gazebo联合仿真框架搭建
2021-05-09
SQL注入
2021-05-09
XCTF-upload1
2021-05-09
LeetCode 题解 | 1. 两数之和
2021-05-09
#2036:改革春风吹满地
2021-05-09
MPI Maelstrom POJ - 1502 ⭐⭐ 【Dijkstra裸题】
2021-05-09
P1379 八数码难题 ( A* 算法 与 IDA_star 算法)
2021-05-09