1、大学大学C+程序设计教程程序设计教程西安交通大学西安交通大学计算机教学实验中心计算机教学实验中心http:/第第10章章 继承和派生继承和派生u本章目标本章目标1掌握继承和派生的概念,派生类的定义掌握继承和派生的概念,派生类的定义方法。方法。2继承的不同方式对基类成员的访问控制继承的不同方式对基类成员的访问控制3掌握单继承的概念、定义方法、单继承掌握单继承的概念、定义方法、单继承派生类构造函数的执行顺序。派生类构造函数的执行顺序。4.理解多继承的概念理解多继承的概念5.虚基类的概念和定义虚基类的概念和定义1授课内容授课内容u10.1 基类与派生类基类与派生类 u10.2 派生类的继承方式派生类
2、的继承方式 u10.3 派生类的构造函数和析构函数派生类的构造函数和析构函数 u10.4 接口和实现方法的分离接口和实现方法的分离u10.5 显示访问基类成员显示访问基类成员u10.6 使用使用this指针指针2水果的分类水果的分类u310.1 继承和派生继承和派生u从一个或多个以前定义的类从一个或多个以前定义的类(基类基类)产生新类产生新类的过程称为派生,这个新类又称为派生类。的过程称为派生,这个新类又称为派生类。u类的继承(类的继承(inheritance)是指新类从基类那)是指新类从基类那里得到基类的特征,也就是继承基类的数里得到基类的特征,也就是继承基类的数据和函数。据和函数。u派生的
3、新类同时也可以增加或重新定义数派生的新类同时也可以增加或重新定义数据和操作,这就产生了类的层次性。据和操作,这就产生了类的层次性。u派生就是创建一个具有别的类的属性和行派生就是创建一个具有别的类的属性和行为的新类的能力。派生和继承的概念也来为的新类的能力。派生和继承的概念也来自于人们认识客观世界的过程。自于人们认识客观世界的过程。4层次概念层次概念u客观世界本身是有层次的,人们认识客观世界本身是有层次的,人们认识客观世界的过程中,由一般到特殊的客观世界的过程中,由一般到特殊的演绎思维发挥着巨大作用。演绎的过演绎思维发挥着巨大作用。演绎的过程在绝大多数情况下就表现为层次分程在绝大多数情况下就表现
4、为层次分类的过程。继承使得程序员可以在一类的过程。继承使得程序员可以在一个较一般的类的基础上很快地建立一个较一般的类的基础上很快地建立一个新类,而不必从零开始设计每个类。个新类,而不必从零开始设计每个类。5u继承常用来表示类属关系,不能将继继承常用来表示类属关系,不能将继承理解为构成关系。当从现存类中派承理解为构成关系。当从现存类中派生出新类时,可以对派生类做如下几生出新类时,可以对派生类做如下几种变化:种变化:可以增加新的数据成员;可以增加新的数据成员;可以增加新的成员函数;可以增加新的成员函数;可以重新定义已有的成员函数;可以重新定义已有的成员函数;可以改变现有成员的属性。可以改变现有成员
5、的属性。6基类基类1基类基类2基类基类n派生类派生类1派生类派生类2基类基类派生类派生类1派生类派生类2(a)多重继承)多重继承 (b)单继承)单继承 一个基类一个基类可以直接可以直接派生出多派生出多个派生类个派生类 派生出来派生出来的新类同的新类同样可以作样可以作为基类再为基类再继续派生继续派生出更新的出更新的类,依此类,依此类推形成类推形成一个一个层次层次结构结构。多重继承与单继承多重继承与单继承 如果一个派生类可以同时有多个基类,称为多重继承如果一个派生类可以同时有多个基类,称为多重继承(multiple-inheritance),这时的派生类同时得到了多个已),这时的派生类同时得到了多
6、个已有类的特征。一个派生类只有一个直接基类的情况称为单一有类的特征。一个派生类只有一个直接基类的情况称为单一继承(继承(single-inheritance)。)。7派生类的定义格式:派生类的定义格式:class 派生类名:访问权限派生类名:访问权限 基类名基类名1,访问限定,访问限定符符 基类名基类名2,访问限定符,访问限定符 基类名基类名n private:成员表成员表1;/派生类增加或替代的私有成员派生类增加或替代的私有成员public:成员表成员表2;/派生类增加或替代的公有成员派生类增加或替代的公有成员protected:成员表成员表3;/派生类增加或替代的保护成员派生类增加或替代的
7、保护成员;/分号不可少分号不可少8u其中基类其中基类1,基类,基类2,是已声明的是已声明的类。类。在派生类定义的类体中给出的成在派生类定义的类体中给出的成员称为派生类成员,它们是新增加的员称为派生类成员,它们是新增加的数据和函数成员。这些新增加的成员数据和函数成员。这些新增加的成员是派生类对基类的发展,它们给派生是派生类对基类的发展,它们给派生类添加了不同于基类的新的属性和功类添加了不同于基类的新的属性和功能。派生类成员包括新添加的,也包能。派生类成员包括新添加的,也包括通过屏蔽作用,取代基类成员的更括通过屏蔽作用,取代基类成员的更新成员新成员9 访问控制访问控制,亦称为,亦称为继承方式继承方
8、式,是对基类成员进一步的限,是对基类成员进一步的限制。访问控制也是三种:制。访问控制也是三种:公有(公有(public)方式,保护)方式,保护(protected)方式和私有()方式和私有(private)方式)方式,亦称公有继承、保,亦称公有继承、保护继承和私有继承。护继承和私有继承。编制编制派生派生类时类时可分可分四步四步 吸收基类的成员吸收基类的成员 改造基类成员改造基类成员 发展新成员发展新成员 重写构造函数与析构函数重写构造函数与析构函数 派生类中成员的变化派生类中成员的变化不论是数据成员,还是函数成员,不论是数据成员,还是函数成员,除构造函数与析构函数外全盘接收除构造函数与析构函数
9、外全盘接收 声明一个和某基类成员同名的新成员派声明一个和某基类成员同名的新成员派生类中的新成员就屏蔽了基类同名成员生类中的新成员就屏蔽了基类同名成员称为同名覆盖(称为同名覆盖(override)派生类新成员必须与基类成员不同名,它派生类新成员必须与基类成员不同名,它的加入保证派生类在功能上有所发展。的加入保证派生类在功能上有所发展。1010.2 派生类的继承方派生类的继承方式式u不可直接访不可直接访问问 u不可直接访不可直接访问问 uprivate u不可直接访不可直接访问问 uprivate uprotected u不可直接访不可直接访问问 uprivate upublic u私有派私有派生
10、生 u不可直接访不可直接访问问 u不可直接访不可直接访问问 uprivate u不可直接访不可直接访问问 uprotected uprotected u可直接访问可直接访问 upublic upublic u公有派公有派生生 u外部函数外部函数void main()u在派生类中在派生类中对基类成员对基类成员的访问限定的访问限定 u基类中基类中的访问限的访问限定定 u派生方派生方式式 在派生类的定义中,基类前所加的访问限定符有两方面含义:在派生类的定义中,基类前所加的访问限定符有两方面含义:派派生类成员(新增成员)函数对基类(继承来的)成员的访问生类成员(新增成员)函数对基类(继承来的)成员的访
11、问(调用和操作)(调用和操作),和,和从派生类对象之外对派生类对象中的基从派生类对象之外对派生类对象中的基类成员的访问类成员的访问。公有派生是绝对主流公有派生是绝对主流。11实例实例:公有继承公有继承(public)class Person/人员类定义人员类定义protected:char Name10;/姓名姓名intAge;/年龄年龄charSex;/性别性别 public:void Register(char*name,int age,char sex);void ShowMe();12class Employee:public Person/雇员类定雇员类定义义char Dept20;
12、/工作部门工作部门float Salary;/月薪月薪public:Employee();void EmployeeRegister(char*name,int age,char sex,char*dept,float salary);void ShowEmp();/显示雇员信息显示雇员信息;13保护继承保护继承(public)u保护继承方式创建的派生类对基类保护继承方式创建的派生类对基类各种成员访问权限如下各种成员访问权限如下:基类的公有成员和保护成员都相当于派基类的公有成员和保护成员都相当于派生类的保护成员,派生类可以通过自身生类的保护成员,派生类可以通过自身的成员函数或其子类的成员函数访
13、问他的成员函数或其子类的成员函数访问他们们对于基类的私有成员,无论派生类内部对于基类的私有成员,无论派生类内部成员或派生类使用者都无法直接访问成员或派生类使用者都无法直接访问 1410.3 派生类的构造函数和析构函数派生类的构造函数和析构函数u派生类构造函数的一般形式为:派生类构造函数的一般形式为:派生类名:派生类名(参数总表):基类派生类名:派生类名(参数总表):基类名名1(参数表(参数表1),),基类名,基类名n(参数表(参数表n),),内嵌对象名内嵌对象名1(对象参数表(对象参数表1),),内,内嵌对象名嵌对象名m(对象参数(对象参数表表m)派生类新增加成员的初始化;派生类新增加成员的初
14、始化;u派生类与基类的析构函数没有什么联系,彼派生类与基类的析构函数没有什么联系,彼此独立,派生类或基类的析构函数只作各自此独立,派生类或基类的析构函数只作各自类对象消亡前的善后工作类对象消亡前的善后工作15派生类构造函数各部分的执行派生类构造函数各部分的执行次序为:次序为:1.调用基类构造函数,按它们在派生类定义的先调用基类构造函数,按它们在派生类定义的先后顺序,顺序调用。后顺序,顺序调用。2.调用内嵌对象构造函数,调用次序按各个对象调用内嵌对象构造函数,调用次序按各个对象在派生类内声明的顺序。在派生类内声明的顺序。3.派生类的构造函数体中的操作。派生类的构造函数体中的操作。*在派生类构造函
15、数中,只要基类不是使用缺省在派生类构造函数中,只要基类不是使用缺省构造函数都要显式给出基类名和参数表。如果构造函数都要显式给出基类名和参数表。如果基类没有定义构造函数,则派生类也可以不定基类没有定义构造函数,则派生类也可以不定义,全部采用系统给定的缺省构造函数。如果义,全部采用系统给定的缺省构造函数。如果基类定义了带有形参表的构造函数时,派生类基类定义了带有形参表的构造函数时,派生类就应当定义构造函数。就应当定义构造函数。16例例10-3 派生类构造函数和析构派生类构造函数和析构函数的执行函数的执行#include#include class Person char Name10;intAge
16、;public:Person(char*name,int age)strcpy(Name,name);Age=age;coutconstructor of personNameendl;Person()coutdeconstrutor of personNameendl;17class Employee:public Personchar Dept20;Person Wang;public:Employee(char*name,int age,char*dept,char*name1,int age1):Person(name,age),Wang(name1,age1)strcpy(Dept,
17、dept);coutconstructor of Employeeendl;Employee()coutdeconstrucor of Employeeendl;18int main()Employee emp(张弓长张弓长,40,人事处人事处,李木子李木子,36);return 0;19派生类构造函数的执行次序派生类构造函数的执行次序u首先,调用基类构造函数,调用顺序首先,调用基类构造函数,调用顺序按照它们被继承时声明的基类名顺序按照它们被继承时声明的基类名顺序执行。执行。u其次,调用内嵌对象构造函数,调用其次,调用内嵌对象构造函数,调用次序按各个对象在派生类内声明的顺次序按各个对象在派生类
18、内声明的顺序。序。u最后,执行派生类构造函数体中的内最后,执行派生类构造函数体中的内容。容。20析构函数析构函数 u派生类析构函数执行过程恰与构造函派生类析构函数执行过程恰与构造函数执行过程相反。数执行过程相反。首先执行派生类析构函数首先执行派生类析构函数然后执行内嵌对象的析构函数然后执行内嵌对象的析构函数最后执行基类析构函数最后执行基类析构函数 21自学内容自学内容u接口与实现方法的分离接口与实现方法的分离u显式访问基类成员显式访问基类成员uthis指针指针22程序设计举例程序设计举例u例例10-6 一个基类及其两个派生类一个基类及其两个派生类u例例10-7 多重继承,从多个基类派生出来的类
19、多重继承,从多个基类派生出来的类class Derived:public Base1,public Base2double real;public:Derived(int,char,double);double getReal()const;void Output();23编程实例:棋子类编程实例:棋子类class ChineseStone :public Stonechar strType10;/棋子类型棋子类型intR;/棋子半径棋子半径public:ChineseStone(int color,int col,int row,char*type);/构造函数构造函数void Show();/显示信息显示信息;24补充习题补充习题u1.定义一个定义一个Point类,其成员有类,其成员有x,y;从从Point派生派生Rectangle类,添加成员类,添加成员l,w;从从Rectangle类派生类派生Box类,添加成员类,添加成员h;编写主程序验证。编写主程序验证。25