【问题标题】:Multiple (diamond) inheritance compiles without "virtual", but doesn't with多重(菱形)继承在没有“虚拟”的情况下编译,但没有
【发布时间】:2011-11-05 09:41:47
【问题描述】:

给定以下代码(没有虚拟继承):

class A
{
public:
    virtual void f() = 0;
};

class B : public A
{
 public:
    virtual void f() {}
};

class C : public A
{
 public:
    virtual void f() {}
};

class D : public B, public C
{

/* some code */
};


int main()
{
    D d;
    return 0;
}

代码编译。

另一方面,这里:

class A
{
public:
    virtual void f() = 0;
};

class B : virtual public A
{
    virtual void f() {}
};

class C : virtual public A
{
    virtual void f() {}
};

class D : public B, public C
{
    /* some code */
};


int main()
{
    D d;
    return 0;
}

编译器出现编译错误:

no unique final overrider for 'virtual void A::f()' in 'D' . 

为什么第二个代码不一样?

【问题讨论】:

  • D 是否实现/覆盖virtual void f()
  • 虚拟继承并不是解决重复继承问题的灵丹妙药。它是与非虚拟继承不同的工具,很像虚拟与非虚拟函数:它们具有不同的语义,适用于不同的问题。

标签: c++ overriding virtual multiple-inheritance virtual-inheritance


【解决方案1】:

通过虚拟继承,D 对象具有单个基类 A 子对象。这个单一的子对象不能有两个不同的虚函数实现。相反,如果没有虚拟继承,D 对象有两个不同的基类A 子对象,每个子对象都有自己的函数实现(在您尝试在D 对象上调用它之前,这是可以的,在哪一点你需要指出你想要哪一个)。

干杯&hth。

【讨论】:

    【解决方案2】:

    您的第一个场景层次结构对应于:

        F()   F()
         A     A
         |     |
     F() B     C F()
          \   /
            D 
    

    其中 D 不是抽象的,因为 D 类型的对象中有两个 A 子对象:一个由 B 通过 B 的晶格具体化,另一个通过 C 的晶格具体化。

    除非您尝试在 D 的对象上调用函数 F(),否则不会有任何歧义。

    您的第二个场景层次结构对应于:

           F()  
            A
          /   \
     F() B     C F()
          \   /
            D  
    

    在这种情况下,对象 D 有一个基类 A 子对象,它必须覆盖并提供该子对象中纯虚函数的实现。


    Herb Sutter 在 Guru Of The Week(GOTW) 中的文章是多重继承的好读物:

    1. Multiple Inheritance Part I
    2. Multiple Inheritance Part II
    3. Multiple Inheritance Part III

    【讨论】:

    • 即使A::f() 不是纯虚拟的,也会发生编译错误。见link
    猜你喜欢
    • 1970-01-01
    • 2014-10-12
    • 2012-07-10
    • 1970-01-01
    • 2014-06-28
    • 1970-01-01
    • 2017-12-12
    • 1970-01-01
    相关资源
    最近更新 更多