




免费预览已结束,剩余43页可下载查看
下载本文档
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
2020年5月3日1时12分,1,C+面向对象程序设计,普通高等教育“十一五”国家级规划教材中国高等院校计算机基础教育课程体系规划教材,谭浩强编著,湖南工业大学计算机与通信学院,2020年5月3日1时12分,2,第11讲继承与派生,11.1授课内容继承与派生的应用。主要内容:1多重继承;2虚基类;3继承与派生的应用。,2020年5月3日1时12分,3,第11讲继承与派生,11.2授课要求(1)理解多重继承的含义、定义方法和实现;(2)理解虚基类及其作用。,2020年5月3日1时12分,4,第11讲继承与派生,11.3授课重点1重点是多重继承和派生类的应用。11.4授课难点1难点是派生类的应用。,2020年5月3日1时12分,5,1多重继承,前面讨论了单继承,即一个类是从一个基类派生而来的。实际上,常常有这样的情况:一个派生类有两个或多个基类,派生类从两个或多个基类中继承所需的属性。多重继承:允许一个派生类同时继承多个基类。这种行为称为多重继承(multipleinheritance)。,2020年5月3日1时12分,6,(1)声明多重继承的方法,方法:在单继承的基础上,依次列出多个基类。比如:如果已声明了类A、类B和类C,可以声明多重继承的派生类D:classD:publicA,privateB,protectedC类D新增加的成员D按不同的继承方式的规则继承A,B,C的属性,确定各基类的成员在派生类中的访问权限。,2020年5月3日1时12分,7,(2)多重继承派生类的构造函数,多重继承派生类的构造函数形式与单继承时的构造函数形式基本相同,只是在初始表中包含多个基类构造函数。如:派生类构造函数名(总参数表列):基类1构造函数(参数表列),基类2构造函数(参数表列),基类3构造函数(参数表列)派生类中新增数成员据成员初始化语句派生类构造函数的执行顺序为:先调用基类的构造函数,再执行派生类构造函数的函数体。调用基类构造函数的顺序是按照声明派生类时基类出现的顺序。,排列顺序任意,2020年5月3日1时12分,8,(2)多重继承派生类的构造函数,例1(P176的例5.8)声明一个教师(Teacher)类和一个学生(Student)类,用多重继承的方式声明一个研究生(Graduate)派生类。教师类中包括数据成员name(姓名)、age(年龄)、title(职称)。学生类中包括数据成员name1(姓名)、age(性别)、score(成绩)。在定义派生类对象时给出初始化的数据,然后输出这些数据。,2020年5月3日1时12分,9,(2)多重继承派生类的构造函数,#include#includeusingnamespacestd;classTeacher/声明类Teacher(教师)public:/公用部分Teacher(stringnam,inta,stringt)/构造函数name=nam;age=a;title=t;voiddisplay()/输出教师有关数据coutname:nameendl;coutageageendl;couttitle:titleendl;protected:/保护部分stringname;intage;stringtitle;/职称;,12,13,2020年5月3日1时12分,10,(2)多重继承派生类的构造函数,classStudent/定义类Student(学生)public:Student(charnam,chars,floatsco)strcpy(name1,nam);sex=s;score=sco;/构造函数voiddisplay1()/输出学生有关数据coutname:name1endl;coutsex:sexendl;coutscore:scoreendl;protected:/保护部分stringname1;charsex;floatscore;/成绩;,12,13,2020年5月3日1时12分,11,(2)多重继承派生类的构造函数,classGraduate:publicTeacher,publicStudent/声明多重继承的派生类Graduatepublic:Graduate(stringnam,inta,chars,stringt,floatsco,floatw):Teacher(nam,a,t),Student(nam,s,sco),wage(w)voidshow()/输出研究生的有关数据coutname:nameendl;coutage:ageendl;coutsex:sexendl;coutscore:scoreendl;couttitle:titleendl;coutwages:wageendl;private:floatwage;/工资;,12,2020年5月3日1时12分,12,(2)多重继承派生类的构造函数,intmain()Graduategrad1(Wang-li,24,f,assistant,89.5,1234.5);grad1.show();return0;,程序运行结果如下:name:Wang-liage:24sex:fscore:89.5title:assistancewages:1234.5,11,2020年5月3日1时12分,13,(2)多重继承派生类的构造函数,注意:在两个基类中分别用name和name1来代表姓名,其实这是同一个人的名字。,在两个基类中都使用同一个数据成员名name,?,10,在show函数中引用数据成员时指明其作用域,如:coutname:Teacher:nameendl;,这就是唯一的,不致引起二义性的方法。,可以,发现一个问题:在多重继承时,从不同的基类中会继承一些重复的数据。如果有多个基类,问题会更突出。在设计派生类时要细致考虑其数据成员,尽量减少数据冗余。,2020年5月3日1时12分,14,(3)多重继承引起的二义性问题,这些重复的数据或者同名的成员使用不当,则:会产生的二义性(ambiguous)问题。进一步讨论:如果类A和类B中都有成员函数display和数据成员a,类C是类A和类B的直接派生类。分别讨论下列3种情况:(a)两个基类有同名成员。如图1所示。查看如下程序:,图1,2020年5月3日1时12分,15,(3)多重继承引起的二义性问题,classApublic:inta;voiddisplay();,classBpublic:inta;voiddisplay();,classC:publicA,publicBpublic:intb;voidshow();,intmain()Cc1;c1.a=3;c1.display();return0;,因为:编译系统无法判别要访问的是哪一基类的成员,c1.A:a=3;c1.A:display();,程序编译出错,2020年5月3日1时12分,16,(3)多重继承引起的二义性问题,为清楚起见,图1应改用图2的形式表示。,图2,2020年5月3日1时12分,17,(3)多重继承引起的二义性问题,(b)两个基类和派生类三者都有同名成员。将上面的C类声明改为classC:publicA,publicBinta;voiddisplay();如图3所示。即有3个a,3个display函数。,图3,2020年5月3日1时12分,18,(3)多重继承引起的二义性问题,如果:,intmain()Cc1;c1.a=3;c1.display();return0;,程序能通过编译,也可正常运行。,访问的是派生类C中的成员。,访问同名成员的规则:基类的同名成员在派生类中被屏蔽,成为“不可见”的,或者说,派生类新增加的同名成员覆盖了基类中的同名成员。,2020年5月3日1时12分,19,(3)多重继承引起的二义性问题,请注意:不同的成员函数,只有在函数名和参数个数相同、类型相匹配的情况下才发生同名覆盖,如果只有函数名相同而参数不同,不会发生同名覆盖,而属于函数重载。要在派生类外访问基类A中的成员,应指明作用域A,写成以下形式:c1.A:a=3;/表示是派生类对象c1中的基类A中的数据成员ac1.A:display();/表示是派生类对象c1中的基类A中的成员函数display,2020年5月3日1时12分,20,(3)多重继承引起的二义性问题,(c)如果类A和类B是从同一个基类派生的,如图4所示。classNpublic:inta;voiddisplay()coutA:a=”aendl;classA:publicNpublic:inta1;classB:publicNpublic:inta2;,图4,classC:publicA,publicBpublic:inta3;,2020年5月3日1时12分,21,(3)多重继承引起的二义性问题,怎样才能访问类A中从基类N继承下来的成员呢?,应当通过类N的直接派生类名来指出要访问的是类N的哪一个派生类中的基类成员。如:c1.A:a=3;c1.A:display();,c1.a=3;c1.display();或c1.N:a=3;c1.N:display();,显然不行!因为这样依然无法区别是类A中从基类N继承下来的成员,还是类B中从基类N继承下来的成员。,2020年5月3日1时12分,22,(4)虚基类,从上面的介绍可知:如果一个派生类有多个直接基类,而这些直接基类又有一个共同的基类,则在最终的派生类中会保留该间接共同基类数据成员的多份同名成员。如图7和图8所示。,2020年5月3日1时12分,23,(4)虚基类,图7,图8,在引用这些同名的成员时,必须在派生类对象名后增加直接基类名,以避免产生二义性。如:c1.A:display()。,2020年5月3日1时12分,24,(4)虚基类,在一个类中保留间接共同基类的多份同名成员,这种现象是人们不希望出现的。a.虚基类的作用C+提供虚基类(virtualbaseclass)的方法,使得在继承间接共同基类时只保留一份成员。声明虚基类的一般形式为:class派生类名:virtual继承方式基类名,2020年5月3日1时12分,25,(4)虚基类,现在,将类A声明为虚基类,方法如下:classA/声明基类A;classB:virtualpublicA/声明类B是类A的公用派生类,A是B的虚基类;classC:virtualpublicA/声明类C是类A的公用派生类,A是C的虚基类;注意:虚基类并不是在声明基类时声明的,而是在声明派生类时,指定继承方式时声明的。,2020年5月3日1时12分,26,(4)虚基类,经过这样的声明后,当基类通过多条派生路径被一个派生类继承时,该派生类只继承该基类一次。,2020年5月3日1时12分,27,(4)虚基类,b.虚基类的初始化如果在虚基类中定义了带参数的构造函数,而且没有定义默认构造函数,则在其所有派生类(包括直接派生或间接派生的派生类)中,通过构造函数的初始化表对虚基类进行初始化。例如classA/定义基类AA(inti)/基类构造函数,有一个参数;classB:virtualpublicA/A作为B的虚基类B(intn):A(n)/B类构造函数,在初始化表中对虚基类初始化;classC:virtualpublicA/A作为C的虚基类C(intn):A(n)/C类构造函数,在初始化表中对虚基类初始化;classD:publicB,publicC/类D的构造函数,在初始化表中对所有基类初始化D(intn):A(n),B(n),C(n);,2020年5月3日1时12分,28,(4)虚基类,注意:在定义类D的构造函数时,与以往使用的方法有所不同。规定:在最后的派生类中不仅要负责对其直接基类进行初始化,还要负责对虚基类初始化。C+编译系统只执行最后的派生类对虚基类的构造函数的调用,而忽略虚基类的其他派生类(如类B和类C)对虚基类的构造函数的调用,这就保证了虚基类的数据成员不会被多次初始化。,2020年5月3日1时12分,29,2虚基类的简单应用举例,例2(P185例5.9)在例5.8(P176)的基础上,在Teacher类和Student类之上增加一个共同的基类Person,如所示。作为人员的一些基本数据都放在Person中,在Teacher类和Student类中再增加一些必要的数据。,图11,2020年5月3日1时12分,30,2虚基类的简单应用举例,#include#includeusingnamespacestd;/声明公共基类PersonclassPersonpublic:Person(stringnam,chars,inta)/构造函数name=nam;sex=s;age=a;protected:/保护成员stringname;charsex;intage;,2020年5月3日1时12分,31,2虚基类的简单应用举例,/声明Person的直接派生类TeacherclassTeacher:virtualpublicPerson/声明Person为公用继承的虚基类public:Teacher(stringnam,chars,inta,stringt):Person(nam,s,a)/构造函数title=t;protected:/保护成员stringtitle;/职称;,2020年5月3日1时12分,32,2虚基类的简单应用举例,/声明Person的直接派生类StudentclassStudent:virtualpublicPerson/声明Person为公用继承的虚基类public:Student(stringnam,chars,inta,floatsco)/构造函数:Person(nam,s,a),score(sco)/初始化表protected:/保护成员floatscore;/成绩;,2020年5月3日1时12分,33,2虚基类的简单应用举例,classGraduate:publicTeacher,publicStudent/Teacher和Student为直接基类public:Graduate(stringnam,chars,inta,stringt,floatsco,floatw):Person(nam,s,a),Teacher(nam,s,a,t),Student(nam,s,a,sco),wage(w)voidshow()/输出研究生的有关数据coutname:nameendl;coutage:ageendl;coutsex:sexendl;coutscore:scoreendl;couttitle:titleendl;coutwages:wageendl;private:floatwage;/工资;,2020年5月3日1时12分,34,2虚基类的简单应用举例,/主函数intmain()Graduategrad1(Wang-li,f,24,assistant,89.5,1234.5);grad1.show();return0;,运行结果为name:Wang-liage:24sex:fscore:89.5title:assistantwages:1234.5,2020年5月3日1时12分,35,2虚基类的简单应用举例,可以看到:使用多重继承时要十分小心,经常会出现二义性问题。许多专业人员认为:不要提倡在程序中使用多重继承,只有在比较简单和不易出现二义性的情况或实在必要时才使用多重继承,能用单一继承解决的问题就不要使用多重继承。也是由于这个原因,有些面向对象的程序设计语言(如Java,Smalltalk)并不支持多重继承。,2020年5月3日1时12分,36,*3基类与派生类的转换,由于派生类中包含从基类继承的成员,因此可以将派生类的值赋给基类对象,在用到基类对象的时候可以用其子类对象代替。具体表现在以下几个方面:(a)派生类对象可以向基类对象赋值。可以用子类(即公用派生类)对象对其基类对象赋值。如Aa1;/定义基类A对象a1Bb1;/定义类A的公用派生类B的对象b1a1=b1;/用派生类B对象b1对基类对象a1赋值在赋值时舍弃派生类自己的成员。,2020年5月3日1时12分,37,*3基类与派生类的转换,实际上,所谓赋值只是对数据成员赋值,对成员函数不存在赋值问题。注意:赋值后不能企图通过对象a1去访问派生类对象b1的成员,因为b1的成员与a1的成员是不同的。特别注意:只能用子类对象对其基类对象赋值,而不能用基类对象对其子类对象赋值。因为基类对象不包含派生类的成员,无法对派生类的成员赋值。同理,同一基类的不同派生类对象之间也不能赋值。,Aa1;Bb1;/B是A的公用派生a1=b1;,2020年5月3日1时12分,38,*3基类与派生类的转换,(b)派生类对象可以替代基类对象,向基类对象的引用进行赋值或初始化。如已定义了基类A对象a1,可以定义a1的引用变量:Aa1;/定义基类A对象a1Bb1;/定义公用派生类B对象b1A注意:此时r并不是b1的别名,也不与b1共享同一段存储单元。它只是b1中基类部分的别名,r与b1中基类部分共享同一段存储单元,r与b1具有相同的起始地址。,2020年5月3日1时12分,39,*3基类与派生类的转换,(c)如果函数的参数是基类对象或基类对象的引用,相应的实参可以用子类对象。如有一函数fun:voidfun(A/(假设B是A的派生类)则结果:输出类B的对象b1的基类数据成员num的值。,2020年5月3日1时12分,40,*3基类与派生类的转换,(d)派生类对象的地址可以赋给指向基类对象的指针变量,也就是说,指向基类对象的指针变量也可以指向派生类对象。比如:(参见189例5.10),classStudent/声明Student类public:Student(int,string,float);voiddisplay();private:intnum;stringname;floatscore;,classGraduate:publicStudentpublic:Graduate(int,string,float,float);voiddisplay();private:floatpay;/工资;,2020年5月3日1时12分,41,*3基类与派生类的转换,voidStudent:display()/定义输出函数coutendlnum:numendl;coutname:nameendl;coutscore:scoreendl;voidGraduate:display()/定义输出函数Student:display();/调用Student类的display函数coutpay=payendl;,42,2020年5月3日1时12分,42,*3基类与派生类的转换,intmain()Studentstud1(1001,Li,87.5);Graduategrad1(2001,Wang,98.5,563.5);Student*pt=/调用grad1.display函数,通过指向基类对象的指针,只能访问派生类中的基类成员,而不能访问派生类增加的成员,num:1001name:Liscore:87.5num:2001name:wangscore:98.5,41,需要访问,使用虚函数和多态性,2020年5月3日1时12分,43,4继承与组合,前面讲过:在一个类中可以用类对象作为数据成员,即子对象。对象成员的类型可以是本派生类的基类,也可以是另外一个已定义的类。一个类中以另一个类的对象作为数据成员的,称为类的组合(composition)。例如,声明Professor(教授)类是Teacher(教师)类的派生类,另有一个类B
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025嘉兴市众业供电服务有限公司招聘74人考前自测高频考点模拟试题及答案详解(网校专用)
- 2025广东省高校毕业生三支一扶计划招募3000人考前自测高频考点模拟试题附答案详解(完整版)
- 2025年潍坊护理职业学院公开招聘高层次(高技能)人才(10人)模拟试卷及答案详解(名师系列)
- 安全培训教学竞赛课件
- 2025河北保定市雄安新区雄县事业单位招聘89人模拟试卷及完整答案详解一套
- 河北省【中职专业高考】2025年中职高考对口升学(理论考试)真题卷【旅游大类】模拟练习
- 居间协议打印版本5篇
- 广播体操课件铃声
- 2025安徽安庆职业技术学院招聘33人模拟试卷及完整答案详解一套
- 2025年医疗康复器材项目合作计划书
- 学堂在线 战场侦察监视技术与装备 章节测试答案
- DG-TJ08-2120-2025 集体土地所有权调查技术标准
- 2024年上海电子信息职业技术学院招聘笔试真题
- 消化内科重点专科申报
- 脑梗死健康宣教及指导
- 山东2025年中小学国防教育知识竞赛
- 脑卒中的饮食护理课件
- 遵守安全生产法 当好第一责任人
- 2025秋统编版小学道德与法治二年级上册教学设计(附目录)
- 秋分主题班会课件
- 民政政策宣讲课件
评论
0/150
提交评论