一、什么是继承和派生
创新互联长期为千余家客户提供的网站建设服务,团队从业经验10年,关注不同地域、不同群体,并针对不同对象提供差异化的产品和服务;打造开放共赢平台,与合作伙伴共同营造健康的互联网生态环境。为蔡甸企业提供专业的网站设计制作、做网站,蔡甸网站改版等技术服务。拥有10多年丰富建站经验和众多成功案例,为您定制开发。
封装、继承、多态是C++的三个重要的特性。在面向对象的技术中强调软件的可重用性,而继承机制就是用来解决软件的重用问题。在C++中,所谓“继承”就是在一个已经存在的类的基础上建立一个新的类。已经存在的类成为基类或父类,新建立的类称为派生类或子类。
一个类从一个已有的类那里获得已有的特性,这种现象称为类的继承。通过继承,一个新建的子类从父类那里获得父类的特性。从另一角度说,从已有的类(父类)产生一个新的类(子类),称为类的派生。派生类继承类基的所有数据成员和成员函数,并可以对成员做出必要的调整。一个基类可以派生出多个派生类,每一个派生类又能作为基类再派生出新的派生类。因此基类和派生类是相对而言的。类的每一次派生都继承了其基类的基本特征,同时又根据需要做出新的调整。一个派生类只从一个基类派生,这种称为单继承。一个派生类也有从两个或多个基类,这种称为多继承。关于基类和派生类的关系可以理解为:基类是派生类的抽象,派生类是基类的具体化。
二、派生类的声明方式
声明一个单继承的派生类的一般形式:
class 派生类名:继承方式 基类名
{
派生类新增加的成员
};
其中继承方式有三种:public(公用的),protected(受保护的),private(私有的)。此项如果不写则默认为private(私有的)。
例:假设已经声明了一个基类Time,在此基础上通过单继承声明一个派生类Date
classDate:publicTime //公用继承
{
public:
voiddisplay()
{
cout << _year << _month << _day << endl;
}
private:
int_year;
int_month;
int_day;
};
三、派生类的构成
派生类的成员包括从基类继承过来的成员和自己增加的成员两大部分。但是并不是说把基类的成员和派生类增加的成员简单的加在一起就成为了派生类。构造一个派生类包括以下3个部分:
1、从基类接受成员
派生类把基类全部成员(不包括构造和析构函数)接受过来。不能选择接受一部分而舍弃另一部分,这是不可选择的。因此如果不能合理的选择基类的话,会造成数据的冗余。
2、调整从基类接收的成员
虽然接受基类成员是不可选择的,但是可与对这些成员做出调整,例如同继承方式改变基类成员在派生类中的访问属性。此外,还可以在派生类中声明一个与基类成员同名的成员,则派生类中的新成员会覆盖基类的同名成员。要注意,如果是成员函数的话,不仅要求函数名相同,还要求函数的参数列表也相同。
3、在派生类中增加新的成员
基类只是提供了最基本的功能,而另有些功能未实现,所以就需要在声明派生类时加入某些具体的功能,形成适用于某一特定应用的派生类。此外,在声明派生类时,一般还有定义适用于派生类的构造函数和析构函数。
四、派生类成员的访问属性
1、基类成员函数只能访问基类成员
2、派生类成员函数可以访问派生类自己增加的成员
3、基类的成员函数不能访问派生类新增加的成员。
4、派生类成员函数在类内或类外访问基类的成员,这种情况比较复杂,它不仅取决于基类成员在基类中的访问属性,还要考虑派生类所声明的对基类的继承方式。
那么就会出现一个问题,在类E中会保存3份类A的成员,如果人们只需要一份类A的成员,那么这种情况下就会占用较多的内存空间,还增加访问的难度。而在实际中人们往往只需要一份类A的成员。为了解决这个问题,C++中提供了虚基类的方法,使得在继承间接共同基类时只保留一份成员。
现在将类A声明为虚基类:
class A
{...};
class B:virtual public A //A是B的虚基类
{...};
class C:virtual public A //A是C的虚基类
{...};
class D:virtual public A //A是D的虚基类
{...};
注意:虚基类并不是在声明基类时声明的,而是在声明派生类时,指定继承方式时声明的。
声明虚基类的一般方法如下:
class 派生类名:virtual 继承方式 基类名
经过虚基类的声明后,当基类通过多条派生路径被一个派生类继承时,该派生类值继承该派生类一次,即基类成员派生类只保留一次。
1、虚基类的初始化
class A
{
A(int i=0){}
...};
class B:virtual public A //A是B的虚基类
{
B(int j=2):A(j){}
...};
class C:virtual public A //A是C的虚基类
{
C(int k=3):A(k)()
...};
class D:virtual public A //A是D的虚基类
{
D(int n=4):A(n){}
...};
class E:public B,public C,public D
{
E(int i=0,int j=0,int k=0,int n=0):A(i),B(j),C(k),D(n){}
...};
注意:
在定义类E的构造函数时,与以往使用的方法有所不同,由于虚基类在派生类中只有一份数据成员,所以这份数据成员必须由派生类之间给出。规定:在最后的派生类中不仅要负责对其之间基类进行初始化,还有负责对虚基类进行初始化。C++编译系统只执行最后的派生类对虚基类的构造函数的调用,而忽略虚基类的其他派生类对虚基类构造函数的调用。
九、基类与派生类的转换
派生类是继承了基类的数据成员,那么基类对象与派生类对象之间是否存在赋值关系,可否进行类型的转换???
答案是可以的。基类对象与派生类对象之间 有赋值兼容的关系,由于派生类中包含从基类中继承的成员,因此可以将派生类的值赋给基类对象,在使用基类对象的时候可以用派生类对象替代。但是注意,这种关系是单向的,不可逆的。
具体有以下4个方面:
1、派生类对象可以向基类对象赋值,这种关系是单向的。
2、派生类对象可以代替基类对象向基类对象的引用进行赋值或初始化。
3、如果函数的参数是基类对象的或基类对象的引用,相应的实参可以是派生类的对象。
4、派生类的地址可以赋给指向基类对象的指针。即指向基类的指针可以指向派生类的对象。不过,指向的是派生类对象中从基类继承的部分。