【问题标题】:How to refactor class hierarchies to avoid diamond problem?如何重构类层次结构以避免钻石问题?
【发布时间】:2018-11-02 23:40:15
【问题描述】:

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

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

  1. (实现)class BX 应该使用来自class Bf(...)g(...),以及来自class X 的所有方法。
  2. (接口)class BX 应遵循class A 的接口。

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

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

【问题讨论】:

  • 我不清楚你所说的“不同的参数列表”是什么意思;你的意思是他们都超载和覆盖 f 和 g?
  • 是的,它们都重载并覆盖了 f() 和 g()。
  • 请出示一些minimal reproducible example
  • 重载几乎无关紧要。具有相同名称和不同参数的函数只是不相关的函数。

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


【解决方案1】:

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

【讨论】:

  • 您好,您能解释一下为什么这是 CRTP 吗?我在这里只为A 的每个子类型B 再形成一个子类型BX
【解决方案2】:
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&lt;XB&gt;内,XB的实现,你只能访问A

如果您希望用户只看到A,只需将XBs 公开为A

注意这可能没什么用,因为访问XB/X&lt;XB&gt; 中的任何更改都需要知道您的对象不是A,因为X&lt;XB&gt; 不会修改A 界面中的任何内容.

【讨论】:

  • 您能解释一下为什么我需要使用struct X 再增加一层间接性吗?是否将XB 转换为A?另外,如果A::f(int, int)B::f(double, double),我是否应该在class A中添加两个函数void A::foo() {dof();}; virtual void A::dof() {};并为A的每个子类型B实现dof()
  • @user 您似乎想将X 的实现限制为仅使用A 接口。我试着这样做。
  • 我明白了。我正在阅读 C++PL 第 27.4.1 节,我可以看到你现在在这里做什么。
猜你喜欢
  • 1970-01-01
  • 2011-01-18
  • 1970-01-01
  • 2010-10-16
  • 1970-01-01
  • 1970-01-01
  • 2016-03-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多