C ++中的一些基本继承问题

时间:2013-05-08 06:54:36

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

我现在正在VS2010中学习C ++编程中的OO。我在C ++中遇到了一些基本的继承问题。这是我的代码:

问题1:

class bs
{
public:
    int a;
    virtual void name(){};
};

class A:virtual public bs
{
public:
    int a;
    virtual void name(){};
};


class B:virtual public bs
{
public:
    int a;
    virtual void name(){};
};

class D:virtual public bs
{
public:
    int a;
    virtual void name(){};
};


class C:public A,public B,public D
{

};

编译器给出了错误C2250。当我从每个类中删除虚拟继承时。即。

class bs
{
public:
    int a;
    virtual void name(){};
};

class A:public bs
{
public:
    int a;
    virtual void name(){};
};


class B:public bs
{
public:
    int a;
    virtual void name(){};
};

class D:public bs
{
public:
    int a;
    virtual void name(){};
};


class C:public A,public B,public D
{

};

它生效了。另外,如果我在错误代码中重写C类中的virtual void name(){};,那么编译器就会顺利进行。所以我的问题是为什么有必要强制在虚拟继承情况下重写虚函数,而不必在非虚函数中重写虚函数继承情况。

问题2:

如上面的代码,我想在非虚拟继承情况下添加bs *mybs = new C();

class bs
{
public:
    int a;
    virtual void name(){};
};

class A:public bs
{
public:
    int a;
    virtual void name(){};
};


class B:public bs
{
public:
    int a;
    virtual void name(){};
};

class D:public bs
{
public:
    int a;
    virtual void name(){};
};


class C:public A,public B,public D
{
    virtual void name(){};
};

//bs *mybs = new C(); //C2594

编译器说错误C2594。但是在虚拟继承情况下,编译器没有错误。

class bs
{
public:
    int a;
    virtual void name(){};
};

class A:virtual public bs
{
public:
    int a;
    virtual void name(){};
};


class B:virtual public bs
{
public:
    int a;
    virtual void name(){};
};

class D:virtual public bs
{
public:
    int a;
    virtual void name(){};
};


class C:public A,public B,public D
{
    virtual void name(){};
};

bs *mybs = new C();//It is OK

虚拟继承情况有什么问题?

我认为这两个问题并不难,但在C ++中是基本的。但是,我不熟悉C ++版本中的OO。感谢您解决问题。

1 个答案:

答案 0 :(得分:1)

Q1:给定虚拟继承,派生类只获取bs对象的一个​​实例,但有name()的三个实现,并且它不知道使用哪个。如果你非虚拟地导出,则在A,B和D类中嵌入三个bs基,每个基都可以覆盖实现。或者,您已经发现可以使用C中的一个实现替换虚拟继承之后的模糊实现。

Q2:在非虚拟情况下,嵌入的A,B和D对象中有三个bs个基数:您希望指向哪一个?这是不明确的,所以你得到错误。如果您使用了虚拟继承,那么只有一个bs基础对象,您可以获得指向它的指针。

举例说明:

 VIRTUAL            NON-VIRTUAL
 .       bs          bs  bs  bs
 .     /  |  \       |   |   |
 .     A  B  D       A   B   D
 .     \  |  /        \  |  /
 .        C              C

在左侧,您的问题C不知道要使用A::name()B::name()D::name()中的哪一个,除非您覆盖了{{1}中的所有三个}。

在右侧,您的问题是C不知道指向哪个b* my_b_ptr基地。