C++学习day23之多继承

从继承的类别上分,继承可以分成多继承和单继承,前面讲的都是单继承。这里其实很容易划分,单继承就是一个父类,多继承就是多个父类。在生活当中有什么意思呢,生活当中,鱼与熊掌不可兼得。但是到了计算机就可以实现,生成一种新的对象,叫做熊掌鱼,多继承自鱼和熊掌即可。再拿我们的沙发床来说,即可以当沙发又可以当床。

#include<iostream>
using namespace std;

class sofa
{
public:
    void sit()
    {
        cout<<"have a seat and have a rest"<<endl;
    }
};

class bed
{
public:
    void sleep()
    {
        cout<<"go to bed and have a sleep"<<endl;
    }
};

class sofabed:public bed,public sofa
{


};

int main()
{
    sofabed a;
    a.sleep();
    a.sit();
    return 0;
}

#include<iostream>
using namespace std;
/*
 *多继承不要想得太好,也有很多不好的问题
 *第一个就是三角问题
 */
/*
 *假设我们不情愿的在两个父类中设计了名字相同的东西,
 * 就像下面的 class X中的int _d,class Y中的int _d;
 * 有一天我想把这两个东西同时继承,或者你还可以这么想
 *假设你父类当中有个operator=,operator=。但是这种问题是
 *我们没法回避的问题,于是你继承它们的时候,你在子类某个函数中能不能
 *随便用operator,不能,因为他不确定你用的本类,不可能用到父类的。因为父类的
 *被shadow,所以你用到父类就要加父类的作用域。然后你用的时候第一你会发现
 *子类当中shadow了父类中的operator=。在子类中只能调用子类的operator=;
 *3.在完成子类的赋值重载的时候不要直接调用operator=,而要用父类::operator=
 *如果说只有一个X里面的是_b,Y里面的是_d还好一点点,我在类里面访问b,d是没问题的。但是问题就是你两个里面都是_d.他就起了冲突。你就只能加作用域了。
 */ 
class X
{
public:
    int _d;
    void SetData(int i)
    {
        _d=i;
    }
};

class Y
{
public:
    int _d;
    int  GetData()
    {
        return _d;
    }

};

class Z:public X,public Y
{
public:
    void dis()
    {
        cout<<X::_d<<endl;
        cout<<Y::_d<<endl;
    }
};

int main()
{
    Z z;
    z.dis();
    int i;
    //你敢用z::_d吗,显然是不能用的。
    //你只能
    //所以面临两个问题,第一出现了冗余信息,给调用者带来了很多不便。
    //你会发现SetData里面设置的是X里面_d,Y里面是Y里面的_d。不像我们以前的
    //单继承那样,所以你这里要理解成这个是带着作用域的继承。
    z.X::_d=100;
    z.SetData(100);
    i=z.GetData();
    z.dis();
    cout<<i<<endl;
    return 0;
}

#include<iostream>
using namespace std;
/*为了避免调用带来的很多的不便利
 * 要解决的问题:第一:实现Z类中数据只有一份 第二:数据访问便利
 * 提取相同数据到一个共同的类中去,然后让被提取公引式的类,分别虚继承公共类(M)*/ 

//class M 我们叫虚基类
//然后对虚基类的继承方式叫做虚继承
//在多继承中,保存共同基类的多份同名成员,虽然有时是必要的,可以在不同的
//数据成员中分别存放不同的数据。但是大多数情况下我们是不希望出现的。因为保留多份数据成员的拷贝,不仅占用了较多的存储空间,还增加了访问的困难

//为此,C++提供了虚基类和虚继承的机制,实现了在多继承中只保留一份共同成员
//但是这样也方便,假设你要对_d进行初始化。
class M
{
public:
    M(int i)
        :_d(i)
    {
    
    }
    void func()
    {
        cout<<"MMMMMMMMMMMMM"<<endl;
    }
    int _d;
};

class X:virtual public M
{
public:
    X(int i)
    :M(i)
    {
    
    }
    void setData(int d)
    {
        _d=d;
    }
};

class Y:virtual public M
{
public:
    Y(int j)
    :M(j)
    {
    
    }
    int getData()
    {
        return _d;
    }
};

class Z:public X,public Y
{
public:
    /*你z不仅仅要把X,Y搬出来,还要把M搬出来*/
    /*所以这里就设计不好,我这个_d到底是哪个值*/
    /*这里会输出1000,为什么呢,因为其实这个_d只有一份,就是M里面的那一份。*/
    /*所以说X,Y构造函数对_d并没有什么用 这里输出1000*/
    Z()
    :X(10),Y(100),M(1000)
    {
    
    }
    void dis()
    {
        cout<<X::_d<<endl;
        cout<<Y::_d<<endl;
        cout<<_d<<endl;

        func();
    }
};
int main()
{
    Z z;
    //z.setData(100);
    //cout<<z.getData()<<endl;
    z.dis();
    return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值