如何重构班级层次结构以避免钻石问题?

时间:2018-11-02 23:40:16

标签: c++ class templates constructor diamond-problem

假设我有一个很大的类层次结构作为一棵单独的根树,根是class A,因此它的每个后代都有自己的void f(...)void g(...)实现,并带有不同的参数列表。

我还有另一个类class X: public A,在其某些方法中仅使用基类f(...)g(...)。现在,我想将X中的方法扩展到A的所有子类型:假设A的子类型为B,新类为class BX。要求是:

  1. (实现)class BX应该使用f(...)中的g(...)class B,以及class X中的所有方法。
  2. (界面)class BX应该遵守class A的界面。

我想出的解决方案是使用template<typename B> class BX: public B来避免1中出现钻石问题。

有没有更好的方法来实现我想要的?

2 个答案:

答案 0 :(得分:0)

根据我的经验,如果您仅继承接口(仅虚拟)并使用合成和委托来共享实现,那么继承的许多问题就会消失,但是奇怪的是重复使用的模板模式或CRTP,这就是您在这里使用的是解决此问题的另一种常用方法。

答案 1 :(得分:0)

template<class D>
struct X {
  A* self(){ return static_cast<D*>(this); }
  A const* self() const{ return static_cast<D*>(this); }
  void foo(){
    self()->f( 1, 2, 3 );
  }
};

struct XA: A, X<XA> {};
struct XB: B, X<XB> {};

X<XB>(实施XB的范围内,您只能访问A

如果您希望用户仅看到A,则仅将XB公开为A

请注意,这可能毫无用处,因为访问XB / X<XB>中的任何更改都需要知道您的对象不是A,因为X<XB>不会被修改A界面中的任何内容。