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

2021-12-17 00:00:00 inheritance multiple-inheritance c++

我有一个用作接口的抽象基类.

I have an abstract base class which acts as an interface.

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

I have two "sets" of derived classes, which implement half of the abstract class. ( one "set" defines the abstract virtual methods related to initialization, the other "set" defines those related to the actual "work". )

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

I then have derived classes which use multiple inheritance to construct fully defined classes ( and does not add anything itself ).

所以:(错误的伪代码)

So: ( bad pseudocode )

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 的类继承吗?(我希望如此).

First of all, can I do this? Can I inherit from two classes which are both derived from the same Base? (I hope so).

不过,这是真正的问题"(为了简化示例,我在上面撒了一点谎).

Here is the "real problem", though (I lied a bit above to simplify the example).

我真正做过的是向基类添加非抽象访问器方法:

What I have really gone and done is add non abstract accessors methods to the base class:

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

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

因为,一个常见的习惯用法是将所有虚拟方法设为私有.

Because, a common idiom is to make all virtual methods private.

不幸的是,现在 AbsInit 和 AbsWork 都继承了这些方法,因此 NotAbsTotal 继承了每个两个"(我意识到我可能正在扼杀编译时真正发生的事情).

Unfortunately, now both AbsInit, and AbsWork inherit these methods, and so NotAbsTotal inherits "two of each" ( I realize I may be butchering what is really happening at compile time ).

无论如何,g++ 在尝试使用该类时会抱怨:对成员 init() 的请求不明确".

Anyway, g++ complains that: "request for member init() is ambiguous" when trying to use the class.

我假设,如果我将我的 AbsBase 类用作纯接口,则可以避免这种情况(假设最上面的示例是有效的).

I assume that, had I used my AbsBase class as a pure interface, this would have been avoided ( assuming that the top example is valid ).

所以:- 我的实现是否有偏差?- 这是将虚拟方法设为私有的习惯用法的限制吗?- 我如何重构我的代码来做我想做的事?(提供一个通用接口,但允许一种方法来交换成员函数集合"的实现)

So: - Am I way off with my implementation? - Is this a limitation of the idiom of making virtual methods private? - How do I refactor my code to do what I want? ( Provide one common interface, but allow a way to swap out implementations for "sets" of member functions )

看来我不是第一个:http://en.wikipedia.org/wiki/Diamond_problem

似乎虚拟继承是这里的解决方案.我以前听说过虚拟继承,但我并没有深入了解它.我仍然愿意接受建议.

Seems Virtual Inheritance is the solution here. I have heard of virtual inheritance before, but I have not wrapped my head around it. I am still open to suggestions.

推荐答案

看起来你想做虚拟继承.这是否真的是一个好主意是另一个问题,但您可以这样做:

It looks like you want to do virtual inheritance. Whether that turns out to actually be a good idea is another question, but here's how you do it:


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

基本上,默认的非虚拟多重继承将包括派生类中每个基类的副本,并包括它们的所有方法.这就是为什么你有两个 AbsBase 副本――你的方法使用不明确的原因是两组方法都被加载,所以 C++ 无法知道要访问哪个副本!

Basically, the default, non-virtual multiple inheritance will include a copy of each base class in the derived class, and includes all their methods. This is why you have two copies of AbsBase -- and the reason your method use is ambiguous is both sets of methods are loaded, so C++ has no way to know which copy to access!

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

Virtual inheritance condenses all references to a virtual base class into one datastructure. This should make the methods from the base class unambiguous again. However, note: if there is additional data in the two intermediate classes, there may be some small additional runtime overhead, to enable the code to find the shared virtual base class.

相关文章