C++基础 虚继承

c++之中一个类不能被多次说明为一个派生类的直接基类,但可以多次成为间接基类。

一 非虚继承类

例子:

class B
{
    public:
    int x.....
}
class A1:public B
{
    .....
}
class A2:public B
{
    ......
}
class D:public A1,public A2
{
    ......
}

可以看出,D类继承了A1和A2,而A1和A2继承了B ,也就是说D类有两个B类的成员副本,所以称B是非虚基类。

非虚继承测试:

#include<iostream>
using namespace std;
class B
{
    public:
    B()
    {cout<<"construct called:B\n";}
    ~B()
    {cout<<"destructor called:B\n";}
    int b;
};
class B1:public B
{
    public:
    B1() {cout<<"constuct called:B1\n";}
    ~B1() {cout<<"destruct called:B1"<<endl;}
    int b1;
};
class B2:public B
{
    public:
    B2() {cout<<"constuct called:B2\n";}
    ~B2() {cout<<"destruct called:B2"<<endl;}
    int b2;    
};
class D:public B1,public B2
{
    public:
    D() {cout<<"constuct called:D\n";}
    ~D() {cout<<"destruct called:D"<<endl;}
    int d;
};
void test()
{
    D dd;
    dd.B1::b=5;
    dd.B2::b=10;
    dd.b1=25;
    dd.b2=111;
    dd.d=149;
    cout<<"dd.B1::b="<<dd.B1::b<<"dd.B2::b"<<dd.B2::b<<"dd.b1="<<dd.b1<<"dd.b2="<<dd.b2<<"dd.b"<<dd.d<<endl;
}
int main()
{
    test();
}

运行结果可以自己去试着运行看一下。

运行后第一轮输出的字符,如“construct called:B”等可以看出运行的顺序。

而void test()里面它直接用D dd,并且输出有d1,d2,d,b,而class D里只是定义了int d;所以显而易见是因为继承了B1和B2。还有要注意,为了访问不同版本的d,必须要用作用域指名是那个基类。

虚继承

当我们为了避免产生二义性,直接想用一个dd.b版本的时候,我们就需要把B1和B2对 B的继承说明为虚继承,它的说明形式是在类继承的关键字前面加一个virtual。这样就不用分别再建立dd.B1:: b,dd. B2::b,而是有virtual指引建立指向dd.b的指针。比如,让我们对上面的例子进行改动,利用virtual。

#include<iostream>
using namespace std;
class B
{
    public:
    B()
    {cout<<"construct called:B\n";}
    ~B()
    {cout<<"destructor called:B\n";}
    int b;
};
class B1:virtual public B
{
    public:
    B1() {cout<<"constuct called:B1\n";}
    ~B1() {cout<<"destruct called:B1"<<endl;}
    int b1;
};
class B2:virtual public B
{
    public:
    B2() {cout<<"constuct called:B2\n";}
    ~B2() {cout<<"destruct called:B2"<<endl;}
    int b2;    
};
class D:public B1,public B2
{
    public:
    D() {cout<<"constuct called:D\n";}
    ~D() {cout<<"destruct called:D"<<endl;}
    int d;
};
void test()
{
    D dd;
    dd.B1::b=5;
    dd.B2::b=10;
    dd.b1=25;
    dd.b2=111;
    dd.d=149;
    cout<<"dd.B1::b="<<dd.b<<"dd.B2::b"<<dd.b<<"dd.b1="<<dd.b1<<"dd.b2="<<dd.b2<<"dd.b"<<dd.d<<endl;//这里有改动
}
int main()
{
    test();
}

运行后我们会发现不会出翔二义性了,对象就只有一个b数据成员了。

最后说一句,一个类体系中可以作为虚继承和非虚继承取决于对他的继承方式,于基类本身的定义无关。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

daydr

来吧,尽情的打赏我啊

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值