如何重构类层次结构以避免菱形问题

How to refactor class hierarchies to avoid diamond problem?

本文关键字:问题 层次结构 何重构 重构      更新时间:2023-10-16

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

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

  1. (实现(class BX应该使用class B中的f(...)g(...),以及class X中的所有方法
  2. (接口(class BX应与class A的接口保持一致

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

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

根据我的经验,如果你只继承接口(即仅虚拟接口(并使用组合和委派来共享实现,那么继承的很多问题就会消失,然而,你在这里使用的奇怪的重复模板模式或CRTP是解决这个问题的另一种常见方法。

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接口中的任何内容。