是从纯抽象类(接口)的虚拟继承所必需的 [英] is virtual inheritance from pure abstract classes (interfaces) necessary

查看:277
本文介绍了是从纯抽象类(接口)的虚拟继承所必需的的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为什么在下面的代码中,编译器声称 PureAbstractBase MultiplyInheritedClass 的不明确的基类?我知道我有两个副本 PureAbstractBase MultiplyInheritedClass FirstConreteClass SecondConreteClass 应该派生虚拟地,因为他们是钻石的中间行(这确实解决了下面的代码的问题)。但是,即使我有两个副本的接口,为什么是 MultiplyInheritedClass 中的代码不只是重写和明确选择在中定义的接口类, MultiplyInheritedClass

Why is it that in the code below the compiler complains that PureAbstractBase is an ambiguous base class of MultiplyInheritedClass? I realize I have two copies of the PureAbstractBase in MultiplyInheritedClass and that FirstConreteClass and SecondConreteClass should be derived virtually because they're the middle row of the diamond (and that does indeed fix the problem with the code below). But even though I have two copies of the interface why is it that the code in MultiplyInheritedClass does not just override both and unambiguously pick the interface class defined in MultiplyInheritedClass?

#include <iostream>
using namespace std;

class PureAbstractBase {
  public:
    virtual void interface() = 0;
};

// I know that changing the following line to:
// class FirstConcreteClass : public virtual PureAbstractBase {
// fixes the problem with this hierarchy
class FirstConcreteClass : public PureAbstractBase {
  public:
    virtual void interface() { implementation(); }
  private:
    void implementation() { cout << "This is object FirstConcreteClass\n"; }
};

// I know that changing the following line to:
// class SecondConcreteClass : public virtual PureAbstractBase {
// fixes the problem with this hierarchy
class SecondConcreteClass : public PureAbstractBase {
  public:
    virtual void interface() { implementation(); }
  private:
    void implementation() { cout << "This is object SecondConcreteClass\n"; }
};

class MultiplyInheritedClass : public FirstConcreteClass,
                               public SecondConcreteClass {
  public:
    virtual void interface() { implementation(); }
  private:
    void implementation() { cout << "This is object MultiplyInheritedClass\n"; }
};

此外,为什么我没有下列层次结构的问题?在这种情况下,ConcreteHandler类不具有AbstractTaggingInterface的三个副本?那么为什么它没有和上面的例子一样的问题呢?

Further, why do I not have issues with the following hierarchy? Doesn't the ConcreteHandler class have three copies of the AbstractTaggingInterface in this case? So why doesn't it have the same issue as the example above?

#include <iostream>
using namespace std;

class AbstractTaggingInterface {
  public:
    virtual void taggingInterface() = 0;
};

class FirstAbstractHandler : public AbstractTaggingInterface {
  public:
    virtual void taggingInterface() { cout << "FirstAbstractHandler\n"; }
    virtual void handleFirst() = 0;
};

class SecondAbstractHandler : public AbstractTaggingInterface {
  public:
    virtual void taggingInterface() { cout << "SecondAbstractHandler\n"; }
    virtual void handleSecond() = 0;
};

class ThirdAbstractHandler : public AbstractTaggingInterface {
  public:
    virtual void taggingInterface() { cout << "ThridAbstractHandler\n"; }
    virtual void handleThird() = 0;
};

class ConcreteHandler : public FirstAbstractHandler,
                        public SecondAbstractHandler,
                        public ThirdAbstractHandler {
  public:
    virtual void taggingInterface() = { cout << "ConcreteHandler\n"; }
    virtual void handleFirst() {}
    virtual void handleSecond() {}
    virtual void handleThird() {}
};

我想包装我的所有这一切,因为我最近与一位同事谈话他声称,如果你是从没有任何数据成员的纯虚拟类(接口)继承,则虚拟继承不是必需的。我认为理解为什么前面的代码示例不工作,后者会很长的路要把这直线在我的头(和清除他的意思是什么他的评论)。提前致谢。

I am trying to wrap my head around all of this because I had a conversation with a colleague recently where he claimed that if you were inheriting from pure virtual classes (interfaces) without any data members then virtual inheritance was not necessary. I think understanding why the former code example does not work and the latter does would go a long way to getting this straight in my head (and clear up what exactly he meant by his comment). Thanks in advance.

推荐答案

您需要虚拟继承才能克服钻石模糊性:

You need virtual inheritance to overcome the diamond-ambiguity:

class FirstConcreteClass  : public virtual PureAbstractBase { ... };
class SecondConcreteClass : public virtual PureAbstractBase { ... };






长时间说明:假设您有:


Long-winded explanation: Suppose you have this:

// *** Example with errrors! *** //
struct A { virtual int foo(); };
struct B1 : public A { virtual int foo(); };
struct B2 : public A { virtual int foo(); };
struct C: public B1, public B2 { /* ... */ };  // ambiguous base class A!

int main() {
  A * px = new C;                              // error, ambiguous base!
  px->foo();                                   // error, ambiguous override!
}

虚函数的继承 foo 是不明确的,因为它有三种方式:从 B1 ,从 B2 和从 A 。继承图形成一个菱形:

The inheritance of the virtual function foo is ambiguous because it comes in three ways: from B1, from B2 and from A. The inheritance diagram forms a "diamond":

   /-> B1 >-\
A->          ->C
   \-> B2 >-/



通过继承virtual, struct B1:public虚拟A; 等,您允许 C * 的任何基类调用正确的成员:

By making the inheritance virtual, struct B1 : public virtual A; etc., you allow any baseclass of C* to call the correct member:

struct A { virtual int foo(); };
struct B1 : public virtual A { virtual int foo(); };
struct B2 : public virtual A { virtual int foo(); };
struct C: public B1, public B2 { virtual int foo(); };

我们必须也定义 C :: foo ()这是有意义的,因为 C 不会有一个定义良好的成员 foo

We must also define C::foo() for this to make sense, as otherwise C would not have a well-defined member foo.

一些更多细节:假设我们现在有一个适当的虚拟继承类 C 我们可以根据需要访问所有的虚拟成员:

Some more details: Suppose we now have a properly virtually-inheriting class C as above. We can access all the various virtual members as desired:

int main() {
  A * pa = new C;
  pa->foo();      // the most derived one
  pa->A::foo();   // the original A's foo

  B1 * pb1 = new C;
  pb1->foo();     // the most derived one
  pb1->A::foo();  // A's foo
  pb1->B1::foo(); // B1's foo

  C * pc = new C;
  pc->foo();      // the most derived one
  pc->A::foo();   // A's foo
  pc->B1::foo();  // B1's foo
  pc->B2::foo();  // B2's foo
  pc->C::foo();   // C's foo, same as "pc->foo()"
}

 

更新:正如大卫在评论中所说的,重要的一点是中间类 B1 B2 虚拟继承,以便其他类(在这种情况下 C )可以继承 them ,同时保持 A 的继承。抱歉初始错误,感谢您的更正!

Update: As David says in the comment, the important point here is that the intermediate classes B1 and B2 inherit virtually so that further classes (in this case C) can inherit from them while simultaneously keeping the inheritance from A unambiguous. Sorry for the initial mistake and thanks for the correction!

这篇关于是从纯抽象类(接口)的虚拟继承所必需的的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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