来自两个派生类的多重继承

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

我有两组派生类,它们实现了抽象类的一半。 (一个“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继承了“每个都有两个”(我意识到我可能在编译时会屠杀实际发生的事情)。

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

我假设,如果我使用我的AbsBase类作为纯接口,则可以避免这种情况(假设顶层示例有效)。

所以: - 我的方式与我的实施? - 这是使虚拟方法变为私人方式的限制吗? - 我如何重构我的代码来做我想做的事? (提供一个通用接口,但允许换出成员函数的“集合”实现)

编辑:

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

似乎虚拟继承是这里的解决方案。 我以前听说过虚拟继承,但是我没有把头绕在它周围。 我仍然乐于接受建议。


它看起来像你想做虚拟继承。 事实证明这是否是一个好主意是另一个问题,但以下是你如何做到的:


class AbsBase {...};
class AbsInit: public virtual AbsBase {...};
class AbsWork: public virtual AbsBase {...};
class NotAbsTotal: public AbsInit, public AbsWork {...};

基本上,默认的非虚拟多重继承将在派生类中包含每个基类的副本,并包含其所有方法。 这就是为什么你有两个AbsBase副本 - 并且你的方法使用的原因是模糊的,因为两组方法都被加载,所以C ++无法知道要访问哪个副本!

虚拟继承将所有对虚拟基类的引用压缩为一个数据结构。 这应该使来自基类的方法再次明确。 但是,请注意:如果两个中间类中有其他数据,则可能会产生一些额外的运行时开销,以使代码能够找到共享的虚拟基类。


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

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;

它可以做到,尽管它让人不寒而栗。

你需要使用“虚拟继承”,其语法是类似的

class AbsInit: public virtual AbsBase {...};
class AbsWork: public virtual AbsBase {...};
class NotAbsTotal: public AbsInit, public AbsWork {...};

然后你必须指定你想要使用的功能:

NotAbsTotal::work()
{
    AbsInit::work_impl();
}

(用正确的语法更新)

链接地址: http://www.djcxy.com/p/54827.html

上一篇: Multiple Inheritance from two derived classes

下一篇: Django Import Error: No module named apps