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

2024-03-17

我有一个充当接口的抽象基类。

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

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

所以:(错误的伪代码)

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 类作为纯接口,就可以避免这种情况(假设上面的示例有效)。

所以: - 我的实施还差得远吗? - 这是使虚拟方法私有化的习惯用法的限制吗? - 如何重构我的代码来完成我想要的事情? (提供一个通用接口,但允许一种方法来交换成员函数“集”的实现)

Edit:

看来我不是第一个:http://en.wikipedia.org/wiki/Diamond_problem 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++ 无法知道要访问哪个副本!

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

来自两个派生类的多重继承 的相关文章

随机推荐