Mayuyu带你学虚基类

最近Mayuyu在学习C++,对Mayuyu来说C++还是很容易的,因为人家本来就冰雪聪明啊,哈哈!不开玩笑啦,进入

正题。今天Mayuyu将会带领你们一起来学习虚基类。

 

那么,听到虚基类这个词,你的第一个反应就是什么是虚基类,为什么C++要引入它。那么现在可爱的Mayuyu将会给

你详细探讨。

 

用五个字概括引入虚基类的目的:消除二义性。我们先来看一段代码:

#include <iostream>
#include <string.h>
#include <stdio.h>

using namespace std;

class A
{
    protected:
        int x;
    public:
        void setterA(int x)
        {
            this->x = x;
        }
};

class B:public A
{
    public:
        void changeB()
        {
            x += 10;
        }
};

class C:public A
{
    public:
        void changeC()
        {
            x += 20;
        }
};

class D:public B,public C
{
    public:
        void show()
        {
            cout<<x<<endl;
        }
};

int main()
{
    D *d = new D();
    d->setterA(10);
    d->show();
    return 0;
}

 

嗯,从上面的代码中可以看出,类B和类C继承父类A,同时类D又继承类B和类C。我们都知道,一般情况下,一个类

要继承另一个类,那么子类从父类中继承下来的所有数据都是重新拷贝了一份,而不是共享原来父类的所有数据。

 

那么代码中,类B和类C都拷贝了一份类A的数据,然后呢,类D又来拷贝类B和类C的所有数据。现在在类D中,我们有

一个方法叫做show(),它输出的是x的值。这样问题就来了,x有两份拷贝,调用的是哪一个x,类B的还是类C的?

 

所以到了这里,上述代码编译就会出错,同样的道理主函数中d->setterA(10),到底是调用的类B的setterA()

方法还是类B的setterA()方法,这个不能确定。这个就是我们所说的二义性。那么我们必须要消除这种二义性才

行啊,怎么消除呢?实际上有两种方法:

 

  (1)在调用时候指明要调用所属类的数据,比如修改为cout<<B::x<<endl和d->B::setter(10)。

  (2)让类B和类C拥有同一个拷贝,而不是两个不同的拷贝,这就是我们要讲的虚基类。

 

也就是说,在上面的代码中,A,B,C,D四个类的关系如下:

 

 

而在虚基类中类B和类C共享父类A的所有数据,那么就应该是如下拓扑结构

 

 

这样,因为只有一个拷贝,所以直接用A的数据就不会引起二义性了,这就是引入虚基类的好处。

 

所以,我们总结一下:

    当一个类的多个直接基类是从另一个共同基类派生而来的,这些直接基类中从上一级基类继承来的成员就拥有

相同的名称。在派生类的对象中,这些同名成员在内存中同时拥有多个拷贝。如何进行分辨呢?当然引入虚基类是

好的啦!

 

虚基类的语法格式如下:

 

    class 派生类名:virtual 继承方式 父类名

    {

         //...

    }

 

这样所有的派生类继承同一个基类时只有一个拷贝了,就消除了二义性。

 

现在Mayuyu就可以把原代码修改如下:

 

#include <iostream>
#include <string.h>
#include <stdio.h>

using namespace std;

class A
{
    protected:
        int x;
    public:
        void setterA(int x)
        {
            this->x = x;
        }
};

class B:virtual public A
{
    public:
        void changeB()
        {
            x += 10;
        }
};

class C:virtual public A
{
    public:
        void changeC()
        {
            x += 20;
        }
};

class D:public B,public C
{
    public:
        void show()
        {
            cout<<x<<endl;
        }
};

int main()
{
    D *d = new D();
    d->setterA(10);
    d->show();
    return 0;
}

 

这样编译顺利通过,哈哈!至此虚基类的核心就差不多讲完了。

 

至此,Mayuyu感谢你的阅读!!!求评论!

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值