作者loveflames (咕啾咕啾魔法阵)
看板C_and_CPP
标题[心得] 整理了一下多重继承的相关概念或资料出处
时间Wed Jun 23 12:40:50 2021
(1)菱形继承
导致了二义性问题,有几种方式解决
一种是限制继承深度,让菱形继承无法出现
一种是使用虚拟继承,但虚拟继承本身带来以下问题(细节见Effective C++ Item 40)
虚基类初始顺序较复杂
由最终派生类呼叫虚基类ctor,容易踩坑
占比较多的空间,且影响data存取速度
(2)指标偏移
父类指标与子类指标指向同一实体,但位址未必相同
不过指标拿来做比较运算时相同,因为会隐式转型成父类指标再比较
(3)转型导致虚函数执行结果无法预期
第一种情况是涉及void*,导致转型时指标不偏移
第二种情况是使用不偏移指标的转型:reinterpret_cast
(4)More Effecitve C++ Item M24
影响效能且占比较多的空间
(5)Google C++ Style Guide
多重继承本身带来的效能影响比虚拟继承还高
避免多重实作继承
(6)Effective C++ Item 40
public介面继承 + private实作继承
(7)C++ Core Guidelines C.135
用多重继承表示多个不同的介面,这些介面通常是抽象类
(8)C++ Core Guidelines C.136
用多重继承表示实现特性的合并;此item认为优先使用单一继承
(9)Modern C++ Design
第一章的policy based design,结合多重继承跟template
第三章的hierarchy generator,现在可以用variadic template简化
(10)C++ Templates: The Complete Guide 21.3
mixin,能在不复制介面的情况下增加data成员或其他操作
为了增加任意数量的base,会用到variadic template
补充:
mixin跟policy based design都是多重实现继承
前者与派生类有"-ABLE"的关系
後者强调在相同介面下选择何种行为,而不是增加data成员或其他操作
前者应采用public继承,後者应采用private继承
--
※ 发信站: 批踢踢实业坊(ptt.cc), 来自: 125.227.113.163 (台湾)
※ 文章网址: https://webptt.com/cn.aspx?n=bbs/C_and_CPP/M.1624423252.A.26D.html
1F:→ KanzakiHAria: 少用继承多用组合 06/25 12:26
2F:→ loveflames: 优先用组合是当然,不过讲这个又要提bridge pattern了 06/25 12:28
3F:→ loveflames: C++官网也有探讨过这个 06/25 12:28
4F:推 ShenJing: 感谢整理 06/25 15:03
既然推文提到优先使用组合,那麽就进一步讨论这个
基本上就是因为继承的耦合度比较高
除了编译相依性外,修改父类很可能导致子类一起修改,我想了几个可能情境
父类原本没有与子类同名的函数,後来加上去
父类允许的继承深度遭到改变
父类从一般继承改成虚拟继承祖父类
父类有无不变式(invariant)的性质遭到改变
(不知道不变式是什麽的,请参考Google C++ Style Guide跟C++ Core Guidelines)
另外,C++官网列了三个经验法则
https://isocpp.org/wiki/faq/multiple-inheritance
经验法则1:仅当这样做会删除if/switch语句时使用继承
经验法则2:多重继承尽量继承抽象类
经验法则3:考虑bridge pattern跟nested generalization能否作为替代方案
如果采用以上连结内容的观点
以二维(M种产品 + N种颜色)为例,考量三种方案的优缺点
多重继承
优点:可同时为产品维度跟颜色维度提供多型
缺点:多重继承跟虚拟继承带来的问题
可能是优点也可能是缺点:有M x N个实作类别
bridge pattern
优点:将颜色维度分离出去,继承关系变成组合关系
缺点:无法在编译期排除某些组合(例如:背包 + 黑色)
可能是优点也可能是缺点:有M + N个实作类别
nested generalization:
缺点:第一层产品维度 + 第二层颜色维度,无法共享颜色维度的代码
可能是优点也可能是缺点:有M x N个实作类别
※ 编辑: loveflames (125.227.113.163 台湾), 06/25/2021 16:21:34
5F:推 KanzakiHAria: 推推 06/25 21:00
6F:→ DerLuna: 不要用继承 06/27 19:01