来自两个派生类的多重继承
我有一个用作接口的抽象基类.
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.
相关文章