版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第8章继承和派生
教学重点:继承和派生的概念派生类成员的访问控制派生类的构造函数和析构函数第8章继承和派生
C++语言面向对象的重要特性是继承与派生,其中继承(inheritance)是实现软件可重用性的重要机制,可以自动地为一个类提供来自另一个类的传函数和成员数据。人们利用继承可以重复使用已经得到认可、并通过测试的高质量的软件,大大提高软件开发效率和质量。派生是一个类在继承另一个类成员函数和成员数据的基础上,根据需要可以对继承成员函数和成员数据进行覆盖或改写,也可以增加属于自己的成员函数和成员数据,从而产生更具体的对象,以满足更加复杂的业务需要。8.1继承和派生的概念
实例:父母子女。子女在继承父母特征的基础上,通过后天发展,派生出来的新的特征。所谓“继承”就是建立一个新类时,新类从一个已存在的类那里获得其已有特性,这种现象称为类的继承。通过继承,一个新建子类从已有的父类那里获得父类的特性。所谓“派生”就是在继承的基础上增加新的特性。总结:类的继承与派生是用已有的类来建立新类的编程技术,继承与派生所表达的是类与类之间的关系。8.1.1基类与派生类
1.继承与派生8.1继承和派生的概念
如果类与类之间有继承和派生关系,那么他们之间应具备以下三个特征:(1)类与类之间应具有共享特征(包括成员函数和成员数据的共享);(2)类与类之间应具有差别或新增特征(包括覆盖、改写或新增成员函数和成员数据);(3)类与类之间是一种层次结构。下面以交通工具为例说明8.1.1基类与派生类
1.继承与派生交通工具车单车汽车马车共同特征的抽象:载重、速度高速滚动人力推动燃料推动马匹推动交通工具车单车汽车马车已存在的类(例如“交通工具”)称为“基类”或“父类”。新建立的类(例如“飞机”)称为“派生类”或“子类”。一个基类可以派生出多个派生类,每一个派生类又可以作为基类再派生出新的派生类,因此基类和派生类是相对而言的。2.基类与派生类树状结构请注意图中箭头的方向,在本书中约定,箭头表示继承的方向,从派生类指向基类。8.1.2继承与派生的作用1.避免公用代码的重复开发,在减少代码和数据冗余的同时,节省程序开发的时间,提高程序开发的效率和质量。2.通过增强代码一致性来减少模块间的接口和界面。3.通过层次关系来组织对象,使得高层类作为低层类的抽象,有利于程序员掌握对象的共性,在此基础上,就能更快地掌握低层类中的个性特征,给编程与代码重用带来方便。8.1.3派生类的声明
C++中派生类的声明须遵守三个原则:(1)C++允许从一个类或多个类派生出一个类,派生类继承基类的所有成员;(2)派生类可以改变继承过来的成员的访问控制权限,方法是在继承基类的声明前加上存取说明符。(3)合法的存取说明符是public、protected和private.8.1.3派生类的声明
声明一个派生类的一般格式为:class派生类名:派生存取说明符(可省)基类名{ //派生类新增的数据成员和成员函数};
派生类名”是要从基类派生出的新类的名字,“基类名”是一个已经定义好的基类的名字,“派生存取说明符”可以是关键字public或protected或private,派生存取说明符的作用会在后面详细介绍,“派生存取说明符”可以省略,默认为private,即私有派生。//定义一个基类(Student类)classStudent{ public: charname[10];//姓名
intage; //年龄
charsex; //性别
charclassname[20]; //班级名称};//定义一个派生类(GraduateStudent类)classGraduateStudent:publicStudent{ public: charAdvisorname[10];//导师
intqualifiergrade; //资格考试分};8.2派生类成员的访问控制(难点)
8.2.1派生类成员访问控制简介从一个基类派生出一个子类时,可以通过指定派生时的存取说明符来实现对派生类成员的访问控制。既然派生类中包含基类成员和派生类自己增加的成员,就产生了这两部分成员的关系和访问属性的问题。在建立派生类的时候,并不是简单地把基类的私有成员直接作为派生类的私有成员,把基类的公用成员直接作为派生类的公用成员。实际上,对基类成员和派生类自己增加的成员是按不同的原则处理的。8.2.2private、protected与public类成员访问特性
1.private类成员
一个类中的私有(private)成员(包括数据成员和成员函数)只能被它们所在类的成员函数和友元函数访问。
在C++中类成员存取说明符缺省的情况下的存取特征都是私有的(private)。【例8.1】类私有成员的定义和访问#include<iostream>usingnamespacestd;classPerson { //Person类的三个私有成员
charname[10];//姓名
private: intage; //年龄
charsex; //性别}; main() { PersonP1; P1.age=20; //非法 cout<<P1.name<<endl; //非法
return0; }2.public类成员
一个类中的公有(public)成员(包括数据成员和成员函数)可以被程序中任何代码(包括函数)访问,一般情况下,应尽量将类的数据成员声明为私有(private),然后为需要被类外部访问的数据成员提供公有的成员函数,实现对私有成员的设置和访问,这种结构能够向类的客户很好的隐藏实现方法,在有效减少错误的同时,可以增强程序的可修改性。3.protected类成员使用protected声明的称为保护成员。任何一个类的保护成员仅可以被其自己和派生类的所有非静态成员函数和友元函数直接访问,也就是说其他的外部函数是不能访问它的。因此,对于那些既要对外界隐藏,又要能被派生类访问的成员,可以将它们声明为保护成员。
如果基类声明了私有成员,那么任何派生类都是不能访问它们的,若希望在派生类中能访问它们,应当把它们声明为保护成员。如果在一个类中声明了保护成员,就意味着该类可能要用作基类,在它的派生类中会访问这些成员。8.2.3三种派生方式的定义
1.私有(private)派生
在声明一个派生类时将派生方式指定为private的,称为私有派生,用私有派生方式建立的派生类称为私有派生类,其基类称为私有基类。
由私有派生得到的派生类,它从基类继承的成员都将变为私有成员,也就是说通过私有派生,派生类从基类继承来的公有成员和保护成员都将变成派生类的私有成员,这些成员将只能被派生类的成员函数和友元函数访问。需要重点说明的是,基类的私有成员经过私有派生后继续保持其基类的私有成员身份,无法被派生类访问。
2.保护(protected)派生
由保护派生得到的派生类,它从基类继承的公有和保护成员都将变为派生类的保护成员。基类的私有成员经过保护派生后继续保持其基类的私有成员身份,依然无法被派生类访问。
保护派生的特点是:基类的公用成员和保护成员在派生类中都成了保护成员,其私有成员仍为基类私有。也就是把基类原有的公用成员也保护起来,不让类外任意访问。3.公有(public)派生
由公有派生得到的派生类,它从基类继承的成员都将维持原有访问控制特征,即通过公有派生后,派生类从基类继承的公有成员在派生类中仍然是公有成员,保护成员仍然是保护成员,而基类的私有成员经过公有派生后继续保持其基类的私有成员身份,依然无法被派生类访问。8.2.4派生类成员访问控制规则
1.派生类中新增成员的访问控制遵循类成员访问控制的规则。2.基类成员在派生类中的访问控制规则注意:不管是何种派生,基类的private成员永远都不能被其派生类直接访问,但可以通过基类的public和protected成员函数访问。
8.3派生类的构造函数和析构函数8.3.1派生类的构造函数和析构函数的声明类的构造函数是类的一种特殊的成员函数,它的作用主要是为对象分配内存、进行初始化;而析构函数它的作用与构造函数相反。派生类的构造函数声明格式如下:派生类的构造函数名称(参数表):基类的构造函数名(参数表){ //… //派生类构造函数体}classPoint{intx,y; public: Point(inta,intb) //基类的构造函数
{ x=a; y=b; cout<<”ConstructingPointclass\n”; } ~Point() //基类的析构函数
{ cout<<”DestructingPointclass\n”;}};classCircle:publicPoint{ doubleradius; public:
Circle(doubler,inta,intb):Point(a,b)//派生类的构造函数 { radius=r; cout<<”ConstructingCircleclass\n”; } ~Circle() //派生类的析构函数
{ cout<<”DestructingCircleclass\n”; }};派生类中含有对象成员时,其构造函数的声明格式如下:
派生类的构造函数名称(参数表):基类的构造函数名(参数表),对象成员名1(参数表),…对象成员名N(参数表){ //… //派生类构造函数体}classCircle2:publicPoint{ doubleradius; PointP1; public:Circle2(doubler,inta,intb):Point(a,b),P1(a,b)
//派生类的构造//函数,定义时指定了基类的构造函数和对象成员P1的构造函数
{ radius=r; cout<<”ConstructingCircle2class\n”; } ~Circle2() //派生类的析构函数
{ cout<<”DestructingCircle2class\n”; }};8.3.2派生类的构造函数和析构函数的构造规则
1.基类具有显式的构造函数时(1)基类具有不带参数的构造函数派生类既可以自己不定义构造函数,也可以根据需要定义自己的构造函数,构造函数可以带参数也可以省略,在派生类中定义构造函数时还可省略“:基类构造函数名(参数表)”。(2)基类仅有带参数的构造函数派生类必须显式的定义其构造函数,并在声明时指定其基类的某一构造函数和参数表,把参数传递给基类构造函数。2.基类具有隐式的构造函数时当基类没有显式的定义(即隐式的定义)构造函数时,派生类可以根据需要定义自己的构造函数,派生类构造函数的参数表、基类的构造函数名和参数表都可以根据需要省略。8.3.3派生类构造函数和析构函数的调用顺序1.构造函数的调用顺序派生类对象创建的时候,构造函数的执行顺序为:(1)基类的构造函数(2)对象成员的构造函数(3)派生类自身的构造函数2.析构函数的调用顺序与构造函数的调用顺序正好相反
(1)派生类自身的析构函数(2)对象成员的构造函数(3)基类的析构函数【例8.6】派生类Circle2的构造函数和析构函数的执行顺序//…Point和Circle2类的定义main(){ Circle2C1(0.0,1,1); cout<<”-------------programline----------------\n”; return0;}程序的执行结果如下:ConstructingPointclassConstructingPointclassConstructingCircle2class---------------programline----------------------DestructingCircle2classDestructingPointclassDestructingPointclass8.4多重继承(自学)8.4.1多重继承的声明前面讨论的是单继承,即一个类是从一个基类派生而来的。在C++中还允许从多个基类中派生出新的子类,这种派生方法称为多重继承(或多基派生)。这一强大的派生功能可以大大提高软件重用的灵活性。声明的格式如下:class派生类名:派生存取说明符(可省)1基类名1,…,
派生存取说明符N基类名N{ //派生类新增的数据成员和成员函数};【例8.7】多重继承的声明#include<iostream>usingnamespacestd;classCircle1//基类Circle1{protected:intr;public:voidsetx(intx){r=x;}voiddraw(){ cout<<"drawing…\n";}};classCircle2//基类Circle2{protected:intr;public:voidsetx(intx){r=x;}voidwrite(){ cout<<"writing…\n";}};classCircle:publicCircle1,publicCircle2//类Circle公有继承了Circle1和Circle2{public:voidshow(){ cout<<"showing…\n";}};voidmain(){Circlecc;cc.draw();cc.write();cc.show();}8.4.2多重继承的几点说明1.在多重继承中派生类成员的访问控制规则与单一继承规则相同。2.多重继承的构造函数与析构函数定义与单一继承相似,只是在构造函数定义时N个基类的构造函数之间用逗号分隔。3.多重继承虽然功能强大,但也容易造成系统的复杂性,设计时务必正确和谨慎,能用单一继承时尽量不用多重继承。4.多重继承容易产生模糊性,在引用时要注意例如前面例8.7如果按照下面来引用:voidmain(){Circlecc;cc.setx(10);//Circle1的setx还是Circle2的setx?}
voidmain(){Circlecc;cc.Circle1::setx(10);//说明是Circle1中的r为10}8.4.3虚基类
1.虚基类的概念在很多情况下,程序员会定义一些类,而不想将其实例化为任何对象,这样的类称为“虚类”或“抽象类”,因为这种虚类一般都要被用作基类,所以又被称为“虚基类”或“抽象基类”。2.虚基类的声明class派生类名:virtual派生存取说明符(可省)虚基类名{ //派生类新增的数据成员和成员函数};3.虚基类的初始化虚基类初始化时,构造函数的调用顺序规则:(1)同一层派生中包含多个虚基类时,虚基类的构造函数按它们派生时声明的先后次序调用。(2)如某虚基类是由实基类派生而来,则先调用此实基类的构造函数,再调用虚基类的构造函数,最后才是派生类的构造函数。(3)若同一层派生中,同时存在虚基类与实基类,应先调用虚基类的构造函数,再调用实基类的构造函数,最后调用派生类的构造函数。4.虚基类的作用虚基类的作用就是为其他类提供一个合适的基类,以便派生类可以从它那里继承和实现所需的接口。在多重继承时,当派生类的多个基类有一个共同的基类时,为防止产生二义性问题可使用虚基类方法。注意:虚基类并不是在声明基类时声明的,而是在声明派生类时,指定继承方式时声明的。因为一个基类可以在生成一个派生类时作为虚基类,而在生成另一个派生类时不作为虚基类。【例8.11】存在二义性的虚基类多重派生#include<iostream>usingnamespacestd;classBase //基类{ protected: intb;public:Base() {b=1;cout<<”ConstructingBaseclass”<<endl; }};classBase1:publicBase//基类1从Base派生{ public:Base1() {cout<<”ConstructingBase1class”<<endl;cout<<”Baseb=”<<b<<endl; }};classBase2:publicBase //基类2从Base派生{ public:Base2() {cout<<”ConstructingBase2class”<<endl;cout<<”Baseb=”<<b<<endl; }};classDerived:publicBase1,Base2//从两个基类base1和base2多重派生出子类{ public:Derived() { cout<<”ConstructingDerivedclass”<<endl;cout<<”Baseb=”<<b<<endl; }};main(){ DerivedD1; return0;}改成如下语句:classBase1:virtualpublicBaseclassBase2:virtualp
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 【正版授权】 ISO 13465:2024 EN Nuclear energy - Nuclear fuel technology - Determination of neptunium in nitric acid solutions by spectrophotometry
- 2024加工承揽合同协议书
- 吊车地铁隧道施工承包合同:2024版
- 2024版在线教育平台建设及运营合同2篇
- 二零二四年版:云计算服务提供合同(2024年度)
- 2024年度广告安装吊车作业安全合同
- 2024版物业服务管理补充协议
- 二零二四年电信基础设施共建与租赁协议
- 2024全新联合办公租赁合同模板2篇
- 二零二四年度蜜桔农业保险服务合同
- 油气田开发工程车辆租赁合同
- 小标题式作文公开课获奖课件省赛课一等奖课件
- 中国厨房电器行业消费态势及销售状况分析研究报告(2024-2030版)
- 2024年安徽省投资集团控股限公司社会招聘高频难、易错点练习500题附带答案详解
- 24秋国家开放大学《公共关系学》实训任务(5)答案
- 海南省海口市海南省华侨中学2024-2025年八年级上期中考试物理试题(含答案)
- 2.2.3 氯气的实验室制法 课件 高一上学期化学人教版(2019)必修第一册
- 宋关福-构建地理空间AI技术底座创新空间智能软件技术
- 2007债券市场年度分析报告
- 冬季传染病预防-(课件)-小学主题班会课件
- 2024年安全员A证理论考试1000题及答案
评论
0/150
提交评论