【问题标题】:Cost of virtual inheritance from an interface从接口虚拟继承的成本
【发布时间】:2017-12-08 21:35:25
【问题描述】:

这是试图了解使用虚拟基类继承的影响,尤其是关于运行时成本。我想到的情况还涉及 Interfaces(或 ABC)。

   I----------
 / | \        |
D1 D2 D3      Isub
      |     /
      D3Dec

所以,我们有一个接口I,我们有不同的实现D1D2D3。但现在的转折是,有一个特殊的装饰器,它只包装了一些(任意的)I 实现,然后添加了基于通过I 表达的契约的扩展功能。

因此,从逻辑或设计的角度来看,最好通过从I 派生的子接口Isub 来表达这种扩展能力。因此任何Isub 也会自动履行I 合约。

问题:性能影响

现在,要在 C++ 中实现这样的,any 接口 I 的实现必须完成 virtual,同样,Isub 必须从 virtual 继承 I,否则我们'd 最终有两个 I 子对象驻留在 D3Dec 中。

  • 这是否意味着,I 的每个实现都必须在内存布局方面付出代价,并通过棘手的虚拟基偏移调整。正确吗?
  • IIsub 都是纯虚函数,即没有成员且只有纯虚函数时,情况是否不同?那么是否有可能在没有虚拟继承的情况下完成这项工作?
  • 要注意的棘手点是客户端代码仅获得对Isub 的引用。如果客户端调用扩展功能,他们实际上会调用D3Dec 中所述功能的实现,而这又使用另一个I-功能来实现扩展功能,因为显然D3dec 不知道任何关于具体I-实现它装饰。这是否一定意味着我们必须使用虚拟继承?或者是否有任何基于模板的技巧来解决这个问题,但仍然有一个(抽象的)子接口Isub

显而易见的替代方案当然是切断IIsub 之间的链接,将其变成微不足道的混合。这可行,但很丑陋,因为Isub 本身没有多大意义,独立于I。两者甚至在签名等上使用相同的数据类型......

【问题讨论】:

  • 你熟悉钻石继承吗?这基本上就是你在这里所拥有的。我不确定这是不是重复的,但有多个问题可以解决这个问题。
  • 你现在,测量。
  • @kabanus 是的,“死亡之钻”。问题是关于设计权衡和/或超越钻石的方法......
  • 很少有应用程序可以通过几条指令开销来产生可衡量的差异,更不用说关键指令了。我同意@Cheersandhth.-Alf 的观点,如果您对此感到担忧,您需要自己衡量。
  • Isub 派生自I 是不是最好的解决方案?如果Isub 包含指向I 的指针怎么办?

标签: c++ performance multiple-inheritance virtual-inheritance


【解决方案1】:

您可以通过将接口类作为具体类的模板参数来完全避免菱形继承问题。这样就不再需要虚拟类继承了。

class I { ... };

template<class Ifc>
class D3Impl : public Ifc
{ ... };

typedef D3Impl<I> D3;

class Isub : public I { ... };

class D3Dec : public D3Impl<Isub>
{ ... };

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-09-27
    • 1970-01-01
    • 2012-10-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多