可以避免这种钻石继承的情况吗?如何避免?

时间:2019-01-21 09:04:20

标签: c++ c++11 design-patterns

在我的库中,我要导出两个名为IBID的接口。 ID应该是IB,因为我想像IB那样使用ID 外部。此外,我有两个相应的实现,ImplBImplD,并且ImplD也是ImplB,对于使用ImplD像{{1} } 内部

ImplB

上面的代码将导致钻石继承问题

class IB{/*...*/};
class ID : public IB{/*...*/};
class ImplB : public IB{/*...*/};
class ImplD : public ID, public ImplB{/*...*/};

如果我尝试通过使用 IB / \ ImplB ID \ / ImplD 继承来避免这种情况

virtual

,那么将出现另一个潜在的性能问题(向IB投放广告的额外罚款)。

所以问题是:

是不是无法摆脱以上钻石继承的情况?

或者还有另一种绕过上述所有方法的方法,又如何?

2 个答案:

答案 0 :(得分:0)

您问:

  

是否无法消除以上费用?

如果必须使用菱形图案(有时​​会出现),则可以通过某种方式让基数知道类型,从而省去一些dynamic_cast成本。例如,一个枚举,它存储构造函数中提供的类型。由于您随后知道类型,因此可以安全地进行static_cast等操作。另一种方法是将type_id哈希存储为映射的键(但提取type_id性能可能有所不同)。第三种方法是使用CRTP。

答案 1 :(得分:0)

最后,我想出了一种避免钻石问题的方法。想法如下所示。

class IB{/*...*/};
class ID_Exclusive{/*...*/};
class ID : public IB, public ID_Exclusive{/*...*/};
class ImplB : public IB{/*...*/};
class ImplD : public ImplB, public ID_Exclusive{/*...*/};

ID_Exclusive是仅具有IB独有功能的接口,然后ImplD只会仅继承IB一次。从lib客户端的角度来看,IDIB,而ImplD也是lib内部的ImplB

虽然我有办法,但是仍然欢迎其他答案或评论。