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