[C++] 来自两个派生类的多重继承


Answers

您需要将继承声明为虚拟:

struct AbsBase {
          virtual void init() = 0;
          virtual void work() = 0;
};

struct AbsInit : virtual public AbsBase {
          void init() {  }
};

struct AbsWork : virtual public AbsBase {
          void work() { }
};

struct NotAbsTotal : virtual public AbsInit, virtual public AbsWork {
};

void f(NotAbsTotal *p)
{
        p->init();
}

NotAbsTotal x;
Question

我有一个抽象基类作为一个接口。

我有两套派生类,它们实现了抽象类的一半。 (一个“set”定义了与初始化有关的抽象虚拟方法,另一个“set”定义了与实际“work”相关的抽象虚拟方法。)

然后我有派生类使用多重继承来构造完全定义的类(并不添加任何东西本身)。

那么:(坏的伪代码)

class AbsBase {
  virtual void init() = 0;
  virtual void work() = 0;
}

class AbsInit : public AbsBase {
  void init() { do_this(); }
  // work() still abs
}

class AbsWork : public AbsBase {
  void work() { do_this(); }
  // init() still abs
}

class NotAbsTotal : public AbsInit, public AbsWork {
  // Nothing, both should be defined
}

首先,我可以这样做吗? 我可以从两个派生自同一个Base的类继承吗? (但愿如此)。

这是“真正的问题”,虽然(我撒谎了一点,以简化这个例子)。

我真的走了,做的是添加非抽象访问器方法的基类:

class AbsBase {
public:
  void init() { init_impl(); }
  void work() { work_impl(); }

private:
  virtual void init_impl() = 0;
  virtual void work_impl() = 0;
}

因为,一个常见的习惯是使所有的虚拟方法都是私有的。

不幸的是,现在AbsInit和AbsWork都继承了这些方法,所以NotAbsTotal继承了“each of each”(我意识到我可能在编译时会屠杀实际发生的事情)。

无论如何,g ++会抱怨:在尝试使用类时,“请求成员init()是不明确的”。

我假设,如果我用我的AbsBase类作为纯粹的接口,这将被避免(假设顶部的例子是有效的)。

所以: - 我的方式与我的执行? - 这是虚拟方法私有化的一个限制吗? - 我如何重构我的代码做我想要的? (提供一个通用的接口,但允许一种方法来替换成员函数的“集合”的实现)

编辑:

似乎我不是第一个: http : //en.wikipedia.org/wiki/Diamond_problem

似乎虚拟继承是这里的解决方案。 我以前听说过虚拟继承,但是我还没有把自己的头包裹起来。 我仍然接受建议。




你必须开始思考你想要在这里建模的东西。

公共继承应该只能用来模拟“isa”关系,例如,狗是动物,方形是形状等。

看一看Scott Meyer的书“Effective C ++”,一篇关于面向对象设计的各个方面应该被解释为什么的优秀论文。

编辑:我忘了说,虽然迄今为止提供的答案在技术上是正确的,但我不认为他们中的任何一个都能解决你正在模拟的问题,这就是你的问题的关键所在!

HTH

干杯,