在我的库中,我要导出两个名为IB
和ID
的接口。 ID
应该是IB
,因为我想像IB那样使用ID 外部。此外,我有两个相应的实现,ImplB
和ImplD
,并且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投放广告的额外罚款)。
所以问题是:
是不是无法摆脱以上钻石继承的情况?
或者还有另一种绕过上述所有方法的方法,又如何?
答案 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客户端的角度来看,ID
是IB
,而ImplD
也是lib内部的ImplB
。
虽然我有办法,但是仍然欢迎其他答案或评论。