两个派生类的多重继承 [英] Multiple Inheritance from two derived classes

查看:103
本文介绍了两个派生类的多重继承的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



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



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



所以:(坏伪代码)

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

类AbsInit:public AbsBase {
void init(){do_this(); }
// work()仍然是abs
}

类AbsWork:public AbsBase {
void work(){do_this(); }
// init()仍然是abs
}

类NotAbsTotal:public AbsInit,public AbsWork {
//没什么,两者都应定义为
}

首先,我可以这样做吗?我可以继承两个派生自同一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继承了两个(我意识到我可能正在屠杀编译时真正发生的事情)。 / p>

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



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



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



编辑:



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



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

解决方案

看起来你想做虚拟继承。是否真的是一个好主意是另一个问题,但这是你如何做到的:

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

基本上,默认的非虚拟多重继承将包含每个基类的副本在派生类中,并包含其所有方法。这就是为什么你有两个AbsBase副本 - 并且你的方法使用不明确的原因是加载了两组方法,所以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
}

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.

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 ).

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

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 )

Edit:

Seems I am not the first one: 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 {...};

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.

这篇关于两个派生类的多重继承的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆