基于类属关系定义类:继承与派生
组合类非常简单,但是,有时候却不能准确表达对象之间的关系。例如,“学生”是“人”,而不是由“人”组成,它们之间是类属关系,不是组合关系。
此时,我们就需要使用另外一种语法工具——继承(Inheritance)。利用继承,我们可以基于类属关系从已有的数据类型快速派生定制出新的数据类型。
继承,是指具有类属关系的两类对象,其中一类对象自动继承另一类对象的全部属性和行为特征。例如,“学生”是“人”,那么,“学生”就应该继承“人”的全部属性和行为特征,此外,还应该具有作为“学生”所特有的属性和行为特征。
继承、基类和派生类
在定制数据类型描述“学生”时,无需再重复描述“学生”属于“人”的那部分属性和行为特征,只要从“人”那里全部继承过来就可以了。例如,
class CPerson{ …… };
class CStudent : public CPerson { //从CPerson类公有继承而来
private: //学生类特有的属性和行为
string stuid; //学号
double gpa; //平均绩点,Grade Point Average
public:
void select(string course) { …… } //选课
double test(string course) { …… } //考试
……
};
这里,我们就称CStudent从CPerson继承而来,或者说,CPerson派生出CStudent,CStudent是CPerson的派生类,而CPerson则是CStudent的基类或父类。
此后,派生类 CStudent就具有了基类CPerson的全部属性和行为,而且还具有“学生”特有的一些属性和行为特征,如学号、平均绩点、选课、考试等。
定制派生类的语法
通过派生类CStudent的例子,我们不难看出,定制派生类与定制普通类的语法相差不大,区别在于定制派生类需要指明继承谁以及如何继承,一般形式如下:
class 派生类名 : 继承方式 基类名 { //派生类继承基类成员
//在类体中改造基类成员,或者说明派生类特有的成员
};
这里,基类名就回答了继承谁的问题,于是,派生类就自动继承了基类的全部成员(注意:派生类不继承基类的构造函数、析构函数、以及赋值操作符)。
派生类继承了基类成员,但是,这些从基类继承来的派生类成员具有什么样的访问限定呢?是保持原有访问限定,还是有新的规则。因此,定制派生类,还需要确定继承方式,即:在派生类中,来自基类的成员具有什么样的访问限定修饰。
为此,C++语言提供了公有(public)、私有(private)和保护(protected)三种继承方式。其中,公有继承最为常用,私有和保护继承很少用到。
定制派生类的步骤:继承、改造、发展、重写
派生类继承基类成员。但是,继承不仅仅是全盘接收,更重要的是继往开来、发展创新,即我们还需要根据派生类的需求,对基类成员进行改造和发展。
因此,总的说来,通过继承定制派生类,通常需要经过如下的四个步骤:
(1)继承基类成员:确定继承的基类,选择从基类继承的方式;
(2)改造基类成员:修改基类成员的访问限定或者重定义基类成员;
(3)发展派生类成员:定义派生类自身特有的数据成员和成员函数;
(4)重写派生类的构造和析构函数,如果有必要,重写赋值操作符。
接下来,我们就针对这四个步骤,阐述如何约定继承方式,如何修改基类成员的访问限定,如何覆盖基类成员,以及如何重写派生类的构造和析构函数。

