接口的虚拟继承成本

时间:2017-12-08 21:35:26

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

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

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

因此,我们有一个接口I,我们有不同的实现D1D2D3。但现在的问题是,有一个特殊的装饰器,它只包含一些(任意)I实现,然后根据通过I表达的合同添加扩展功能。

因此,从逻辑或设计视角开始,需要通过从Isub派生的子接口I表达扩展能力。因此,任何Isub自动也会履行I合同。

问题:绩效影响

现在,要在C ++中实现此类,接口I任何实现必须完成virtual,同样,Isub必须继承virtual来自I,否则我们最终会在I中找到两个D3Dec子对象。

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

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

1 个答案:

答案 0 :(得分:2)

通过使接口类成为具体类的模板参数,可以完全避免钻石继承问题。然后不再需要虚拟类继承。

class I { ... };

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

typedef D3Impl<I> D3;

class Isub : public I { ... };

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