继承和派生概述:
继承和派生是同一个过程从不同角的度看
保持已有类的特性而构造新类的过程称为继承。
在已有类的基础上新增自己的特性而产生新类的过程称为派生。
被继承的已有类称为基类(或父类)。
派生出的新类称为派生类(或子类)。
直接参与派生出某类的基类称为直接基类。
基类的基类甚至更高层的基类称为间接基类。
派生类成员的访问
不同的继承方式决定了基类成员在派生类中的访问属性
1)公有继承
基类的公有成员和保护成员在派生类中保持原有访问属性,私有成员仍为基类所有。
2)私有继承
基类的所有成员在继承类中为私有成员。
3)保护继承
一般地,保护继承与私有继承在实际编程中极少使用,它们只在技术理论上有意义。
在公有继承中,派生类成员可以访问继承的基类的public部分与protected部分,但是不能访问private部分。只有基类成员以及基类的友元可以访问private部分。
无论采用何种继承方式得到的派生类,派生类成员及其友元都不能访问基类的私有成员。
赋值兼容性规则
赋值兼容规则是指在需要基类对象的任何地方,都可以使用共有派生类的对象来替代。通过公有继承,派生类得到了基类中除了构造函数与析构函数之外的所有成员。这样共有派生类实际就具有了基类的所有功能,凡是基类能解决的问题,公有派生类都可以解决。
class Base{}; //基类 class Derive:public Base{}; //公有派生类 Base b,*pb; //定义基类对象,指针 Derive d; //定义派生类对象
赋值兼容性规则中所指的替代包括如下情况。
(1)派生类的对象可以赋值给基类对象;
b=d; //派生类对象赋值给基类,复制基类继承部分
(2)派生类的对象可以初始化基类的引用;
Base &rb=d; //基类引用到派生类对象
(3)派生类对象的地址可以赋值给指向基类的指针。
pb=&d; //基类指针指向派生类对象
派生类的构造和析构函数
1)构造函数
派生类的构造函数定义形式如下:
派生类名站(形式参数列表):基类名(基类构造函数实参列表),派生类初始化列表
例子:
class Point{int x,y; public:Point(int a,int b):x(a),y(b){} //基类构造函数 }; class Rect:public Point {int h,w; public :Rect(int a,int b,int c,int d):Point(a,b),h(c),w(d){} //派生类构造函数
如果基类有默认构造函数,或者参数全部都是默认参数的构造函数,那么派生类的构造函数中可以不显式初始化子对象。编译器会调用基类的构造函数进行初始化。
多重继承
C++支持一个派生类同时继承多个基类。
多重继承派生类的定义:
class 派生类名:访问标号1 基类名1,访问标号2 基类名2,...{
成员列表
};
多重继承构造函数:
多重继承派生类的构造函数形式与单一继承时的构造函数形式基本相同,只是在派生类的构造函数初始化列表中调用调用多个基类构造函数。一般形式为:
派生类名(形参列表):基类名1(基类1构造函数实参列表)
基类名2(基类2构造函数实参列表)
...
子对象名1(子对象1所属类的构造函数实参列表)
...
派生类初始化列表
{
派生类初始化列表
};
多重继承时,多个基类可能会出现同名的成员。在派生类中对这种基类对象的直接访问会有二义性。C++要求派生类对基类成员的访问必须是无二义性的。这时我们需要使用成员名限定消除二义性:
基类名::成员名 //在派生类内部使用基类成员
对象名.基类名::成员名 //派生类对象使用基类成员
对象指针名->基类名::成员名 //派生类指针使用基类成员