12

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

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

为什么第二个代码不同?

4

2 回答 2

9

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

    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. 多重继承第一部分
  2. 多重继承第二部分
  3. 多重继承第三部分
于 2011-08-28T09:19:50.190 回答
7

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

干杯&hth。

于 2011-08-28T09:10:22.240 回答