【发布时间】:2017-12-08 21:35:25
【问题描述】:
这是试图了解使用虚拟基类继承的影响,尤其是关于运行时成本。我想到的情况还涉及 Interfaces(或 ABC)。
I----------
/ | \ |
D1 D2 D3 Isub
| /
D3Dec
所以,我们有一个接口I,我们有不同的实现D1、D2 和D3。但现在的转折是,有一个特殊的装饰器,它只包装了一些(任意的)I 实现,然后添加了基于通过I 表达的契约的扩展功能。
因此,从逻辑或设计的角度来看,最好通过从I 派生的子接口Isub 来表达这种扩展能力。因此任何Isub 也会自动履行I 合约。
问题:性能影响
现在,要在 C++ 中实现这样的,any 接口 I 的实现必须完成 virtual,同样,Isub 必须从 virtual 继承 I,否则我们'd 最终有两个 I 子对象驻留在 D3Dec 中。
- 这是否意味着,
I的每个实现都必须在内存布局方面付出代价,并通过棘手的虚拟基偏移调整。正确吗? -
I和Isub都是纯虚函数,即没有成员且只有纯虚函数时,情况是否不同?那么是否有可能在没有虚拟继承的情况下完成这项工作? - 要注意的棘手点是客户端代码仅获得对
Isub的引用。如果客户端调用扩展功能,他们实际上会调用D3Dec中所述功能的实现,而这又使用另一个I-功能来实现扩展功能,因为显然D3dec不知道任何关于具体I-实现它装饰。这是否一定意味着我们必须使用虚拟继承?或者是否有任何基于模板的技巧来解决这个问题,但仍然有一个(抽象的)子接口Isub?
显而易见的替代方案当然是切断I 和Isub 之间的链接,将其变成微不足道的混合。这可行,但很丑陋,因为Isub 本身没有多大意义,独立于I。两者甚至在签名等上使用相同的数据类型......
【问题讨论】:
-
你熟悉钻石继承吗?这基本上就是你在这里所拥有的。我不确定这是不是重复的,但有多个问题可以解决这个问题。
-
你现在,测量。
-
@kabanus 是的,“死亡之钻”。问题是关于设计权衡和/或超越钻石的方法......
-
很少有应用程序可以通过几条指令开销来产生可衡量的差异,更不用说关键指令了。我同意@Cheersandhth.-Alf 的观点,如果您对此感到担忧,您需要自己衡量。
-
Isub派生自I是不是最好的解决方案?如果Isub包含指向I的指针怎么办?
标签: c++ performance multiple-inheritance virtual-inheritance