2
#include<iostream>
using namespace std;

class base
{
    public:
      virtual void f(){}
};

class middle1:public base
{};

class middle2:public base
{};

class derive:public middle1,public middle2
{};



int main()
{
    derive* pd=new derive();
    pd->f();
    return 0;
}

我知道 virtual 解决了这个问题,但是如何呢?即使我们没有多重继承,我们是否总是为了安全而编写公共虚拟。

4

3 回答 3

5

每个实例derive都有一个middle1基类子对象和一个middle2基类子对象。

如果继承是非虚的,那么middle1基类子对象有一个base基类子对象,middle2类子对象也有一个base基类子对象。因此, 的每个实例derive都有两个base子对象,并且调用pd->f()是模棱两可的——base你想调用哪个对象f()

使继承成为虚拟意味着middle1并且middle2base共享derive. 这消除了歧义——只有一个base对象f()可以被调用。

为了安全,我们总是可以写公共虚拟的吗

不必要。可能存在您不希望 middle1middle2共享公共base子对象的继承层次结构。您可能会争辩说,在这种情况下,您不应该编写一个derive继承自两者的类,但如果您最终遇到这种情况,那么解决方法是:

static_cast<middle1*>(pd)->f();
pd->middle1::f();

指定要调用fmiddle1类子对象,或

static_cast<middle2*>(pd)->f();
pd->middle2::f();

指定middle2.

于 2013-03-19T11:39:43.713 回答
1

我知道 virtual 解决了这个问题,但是如何呢?

virtual关键字通过使继承层次结构中仅存在一个顶级基类子对象来解决该问题。没有它,每个父类middle1都有middle2自己的base类副本,从而导致歧义。

即使我们没有多重继承,我们是否总是为了安全而编写公共虚拟。

virtual如果您没有多重继承,则没有理由使用继承。多重继承是虚拟继承概念存在的目的。

于 2013-03-19T11:36:50.250 回答
1

虚拟基类实现了一个额外的间接级别以解决菱形问题(参见这个问题)。

如果您始终使用虚拟继承,您将始终遭受额外间接级别导致的性能损失。

因此,我建议您仅在必要时使用虚拟继承。

于 2013-03-19T11:38:11.043 回答