




已阅读5页,还剩52页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
精选,1,第四章继承和派生,精选,2,4.1继承和派生的概念,面向对象程序设计有4个主要特点:抽象、封装、继承和多态性。在本章中主要介绍有关继承的知识,在下一章中将介绍多态性。C+语言提供了类的继承机制,解决了软件重用问题。,4.1.1继承与派生的概念,一个类中包含了若干数据成员和成员函数。在不同的类中,数据成员和成员函数是不相同的。但有时两个类的内容基本相同或有一部分相同。,精选,3,类的继承:一个新类从已存在的类那里获得该类已有的特性叫作类的继承。已存在的类叫作父类,也叫作基类。产生的新类叫作子类或派生类。类的派生:从一个已有的类那里产生一个新类的过程叫类的派生。已存在的类叫作父类,也叫作基类。产生的新类叫作派生类或子类。类的继承和派生是同一概念,前者是从子类的角度来说,后者是从父类的角度来说的。我们通常说子类继承了父类。父类派生了子类。,精选,4,描述各级学生的类的继承关系如下图:,基类与派生类的关系:派生类是基类的具体化,基类则是派生类的抽象一个派生类的对象也是一个基类的对象。应该具有基类的一切属性和方法。派生类除了具有基类的一切属性和方法外,还可以有自己所特有的属性和方法。,4.1.2派生类和基类的关系,精选,5,4.1.3单继承与多继承,单继承:一个派生类只从一个基类继承。,多重继承:一个派生类从两个或多个基类继承。,精选,6,4.2派生类的声明方式,声明派生类的一般形式为class派生类名:继承方式基类名派生类新增加的成员;,继承方式包括:public(公有的),private(私有的)和protected(受保护的),此项是可选的,如果不写此项,则默认为private(私有的)。,如下程序演示了类Rectangle(四边形)由类Point继承而来。,精选,7,voidSetPoint(intx,inty)this-x=x;this-y=y;voidMovePoint(intdx,intdy)x+=dx;y+=dy;voidShowPoint()cout(x,y);,/Point.h#include#includeusingnamespacestd;classPointprivate:intx,y;public:intGetX()returnx;intGetY()returny;,精选,8,voidSetRect(intx,inty,intw,inth)SetPoint(x,y);width=w;height=h;voidShowRect()cout左上角坐标为:;ShowPoint();coutendl;cout宽为:widthendl;cout长为:heightendl;,/Rectangle.h#include#includePoint.husingnamespacestd;classRectangle:publicPointprivate:intwidth;intheight;public:intGetWidth()returnwidth;intGetHight()returnheight;,精选,9,/main.cpp#includeRectangle.hvoidmain()Rectangler;r.SetRect(0,0,10,20);r.ShowRect();r.MovePoint(10,10);r.ShowRect();,精选,10,4.3派生类的构成,派生类中的成员包括从基类继承过来的成员和自己增加的成员两大部分。在基类中包括数据成员和成员函数(或称数据与方法)两部分,派生类分为两大部分:一部分是从基类继承来的成员,另一部分是在声明派生类时增加的部分。每一部分均分别包括数据成员和成员函数。,精选,11,如果在派生类中定义了和基类中同名函数(函数参数个数和类型可以相同也可以不相同),则派生类中的函数会隐藏基类的同名函数。在派生类中不能直接访问基类中的同名函数。(注意与重载的区别。在同一个类中的同名不同参函数为重载函数)如程序PointRect1所示:,精选,12,4.4继承方式,派生类的继承方式有三种:public,private,protected。不同的继承方式决定了基类成员在派生类中的访问属性。,精选,13,4.4.1类的保护成员,前面介绍过类的成员(数据成员和成员函数)的访问属性有私有的(private)的和公有的(public的)。另外还提到类的访问属性也可以有保护的(protected的)。,类中的protected成员与private成员一样,只能在本类的成员函数中访问,不能在类外通过对象来访问。但通过上面的表中可以看出当类派生时,基类的private成员在派生类中是不可访问的。而基类的protected成员在派生类中随继承方式的不同而不同。,精选,14,classDrived:publicBaseprotected:intj;public:voidFun()i=20;,#includeusingnamespacestd;classBaseprotected:inti;public:voidF();,voidmain()Drivedd;,精选,15,4.5派生类的构造函数和析构函数,构造函数的主要作用是对数据成员初始化。在设计派生类的构造函数时,不仅要考虑派生类所增加的数据成员的初始化,还应当考虑基类的数据成员初始化。也就是说,希望在执行派生类的构造函数时,使派生类的数据成员和基类的数据成员同时都被初始化。解决这个问题的思路是:在执行派生类的构造函数时,调用基类的构造函数,注意:派生类继承基类的除构造函数和析构函数以外的所有函数。,精选,16,4.4.1简单的派生类的构造函数,简单的派生类:只有一个基类,而且只有一级派生(只有直接派生类,没有间接派生类),在派生类的数据成员中不包含基类的对象(即子对象)。简单派生类中我们一般采用在派生类的构造函数初始化列表中调用基类的构造函数来对继承基类的数据成员进行初始化。,其一般形式为:派生类构造函数名(总参数表列):基类构造函数名(参数表列)派生类中新增数据成员初始化语句,、简单派生类的构造函数的形式,精选,17,#include#includeusingnamespacestd;classStudentpublic:Student(intn,stringnam,chars)num=n;name=nam;sex=s;Student()protected:intnum;stringname;charsex;,精选,18,classStudent1:publicStudentpublic:Student1(intn,stringnam,chars,inta,stringad):Student(n,nam,s)age=a;addr=ad;voidshow()coutnum:numendl;coutname:nameendl;coutsex:sexendl;coutage:ageendl;coutaddress:addrendly=y;voidPoint:Show()cout(x,y)r=r;voidCircle:Show()cout圆心为:;Point(x,y).Show();cout半径为:rendl;floatCircle:GetArea()return3.14159*r*r;floatCircle:GetLength()return3.14159*2*r;,精选,24,4.5.2有子对象的派生类的构造函数,类的数据成员中还可以包含类对象。例如前面的Student1类继承自Student类,我们可以在Student1类中加入一个Student类的对象来表示该同学所在班的班长。如下程序所示:,#include#includeusingnamespacestd;classStudentpublic:Student(intn,stringnam)num=n;name=nam;voiddisplay()coutnum:numendlname:nameendl;protected:intnum;stringname;,精选,25,classStudent1:publicStudentpublic:Student1(intn,stringnam,intn1,stringnam1,inta,stringad):Student(n,nam),monitor(n1,nam1)age=a;addr=ad;voidshow()cout学生信息为:endl;display();coutage:ageendl;coutaddress:addrendl;cout班长为:y=y;voidPoint:Show()cout(x,y)r=r;voidCircle:Show()cout圆心为:;Point(x,y).Show();cout半径为:rh=h;voidShow();floatGetArea();floatGetVolume();#endif,精选,31,/Column.cpp#includeColumn.h#includeusingnamespacestd;voidColumn:Show()Circle:Show();cout高为:hendl;floatColumn:GetArea()return2*Circle:GetArea()+GetLength()*h;floatColumn:GetVolume()returnCircle:GetArea()*h;,精选,32,在多层派生的情况下:派生类的构造函数初始化列表中只须写出其上一层派生类的构造函数,不要再写上其间接子类的构造函数。,精选,33,4.5.4派生类的析构函数,在派生时,派生类是不能继承基类的析构函数的,也需要通过派生类的析构函数去调用基类的析构函数。在派生类中可以根据需要定义自己的析构函数,用来对派生类中所增加的成员进行清理工作。基类的清理工作仍然由基类的析构函数负责。在执行派生类的析构函数时,系统会自动调用基类的析构函数和子对象的析构函数,对基类和子对象进行清理。调用的顺序与构造函数正好相反:先执行派生类自己的析构函数,对派生类新增加的成员进行清理,然后调用子对象的析构函数,对子对象进行清理,最后调用基类的析构函数,对基类进行清理。,精选,34,4.6多重继承,前面讨论的是单继承,即一个类是从一个基类派生而来的。实际上,常常有这样的情况:一个派生类有两个或多个基类,派生类从两个或多个基类中继承所需的属性。C+为了适应这种情况,允许一个派生类同时继承多个基类。这种行为称为多重继承(multipleinheritance)。,4.6.1声明多重继承的方式,声多重继承子类的方法和单继承相似,只是在标明子类的位置将继承的父类都写上,且以豆号隔开。例如类多重继承了类A,B,C则申明类的方法如下:classD:publicA,protectedB,privateC类新增加的成员,精选,35,多重继承的子类具有多个父类,子类中具有所有父类的所有成员。且对多个父类可以有不同的继承方式,不同的继承方式决定了继承而来的父类的成员在子类中的访问属性的不同。,4.6.2多重继承的派生类的构造函数,多重继承派生类的构造函数形式与单继承时的构造函数形式基本相同,只是在初始列表中包含多个基类构造函数。形式如下:派生类构造函数名(总参数表列):基类1构造函数(参数表列),基类2构造函数(参数表列),基类3构造函数(参数表列)派生类中新增数据成员成员初始化语句,精选,36,派生类构造函数的执行顺序同样为:先调用基类的构造函数,再执行派生类构造函数的函数体。调用基类构造函数的顺序是按照声明派生类时基类出现的顺序,与构造函数初始化列表中基类的排列顺序无关。,#include#includeusingnamespacestd;classTeacherpublic:Teacher(stringnam,inta,stringt)name=nam;age=a;title=t;voiddisplay()coutname:nameendl;coutageageendl;couttitle:titleendl;,精选,37,protected:stringname;intage;stringtitle;classStudentpublic:Student(stringnam,chars,floatsco)name1=nam;sex=s;score=sco;voiddisplay1()coutname:name1endl;coutsex:sexendl;coutscore:scoreendl;,精选,38,protected:stringname1;charsex;floatscore;classGraduate:publicTeacher,publicStudentpublic: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;,精选,39,private:floatwage;intmain()Graduategrad1(Wang-li,24,m,assistant,89.5,1234.5);grad1.show();return0;,在两个基类中分别用name和name1来代表姓名,其实这是同一个人的名字,从Graduate类的构造函数中可以看到总参数表中的参数nam分别传递给两个基类的构造函数,作为基类构造函数的实参。,精选,40,解决这个问题有一个好方法:在两个基类中可以都使用同一个数据成员名name,而在show函数中引用数据成员时指明其作用域,如coutname:Teacher:namea=a;voiddisplay()couta=a;voiddisplay()coutB:a=ab=b;voidshow()A:display();B:display();coutC:b=bendl;voidmain()Cc(1,2,3);/c.display();二义性;c.show();c.B:display();,精选,44,所以类中数据成员全名应该为下图所示:,精选,45,b)多个基类和派生类中都有同名成员,classC:publicA,publicBprivate:inta;public:C(intAa,intBa,intCa):A(Aa),B(Ba)a=Ca;voiddisplay()A:display();B:display();coutC:a=aendl;,将前面的类改为如下的形式:,精选,46,这时类的成员构成如左图所示;在类中有三个a,三个display()函数。,思考:如下的main函数能否执行:voidmain()Cc(1,2,3);c.display();c.A:display();c.B:display();,这时c.dispaly是可以执行的。原因是类中提供的display函数隐藏了基类和基类中的display函数。所以直接访问display函数是在访问类中新增加的成员函数display();,精选,47,C)如果类A和类B是从同一个基类派生的,精选,48,前面提到派生类的对象也是基类的对象,因为派生类中继承了基类中的所有成员(除构造函数和析构函数)。准确的说应该是:公有派生类的对象是基类的对象。因为只有公有派生类中成员的访问属性与基类完全相同。基类能实现的功能在公有派生类中一定能够实现。,4.7基类与派生类的转换,基本数据类型在一定条件下可以进行类型转化,那么基类对象与派生类对象之间是不是也可以进行转化?,由于公有派生类对象也是基类的对象,所以派生类对象可以自动转化为基类对象。表现在以下几方面:,精选,49,#include#includeusingnamespacestd;classPersonpublic:Person(stringnam,chars,inta)name=nam;sex=s;age=a;Person()diplay()cout姓名:nameendl;cout性别:sexendl;cout年龄:ageendl;protected:stringname;charsex;intage;,精选,50,classTeacher:publicPersonpublic:Teacher(stringnam,chars,inta,stringt):Person(nam,s,a)title=t;Teacher()diplay()Person:diplay();cout职称:title;protected:stringtitle;voidmain()/Teachert(zhangSan,m,25,assistant);/Personp=t;/p.diplay();Personp(zhangSan,m,25);Teachert=p;t.diplay();,精选,51,(1)派生类的对象可以赋值给基类对象。,voidmain()Teachert(zhangSan,m,25,assistant);Personp=t;p.diplay();,派生类的对象赋值给基类对象时舍弃了派生类自己增加的成员。只是将由基类继承而来的数据成员的值赋给基类对象的相应成员。基类的对象不能够赋值给派生类。如下代码错误Personp(“zhangSan”,m,25);Teachert=p;/errort.diplay();,精选,52,(2)派生类的地址可以赋值给基类的指针。,voidmain()Teachert(zhangSan,m,25,assistant);Personp(Lisi,f,26);Person*pp=,用派生类对象的地址来初始化基类指针后,只能通过该指针访问派生类中继承的基类的成员。不能访问派生类中增加的成员。,精选,53,()派生类的对象可以赋值给基类的引用。,voidmain()Teachert(zhangSan,m,25,assistant);Person,用派生类对象来初始化基类引用,引用变量只是派生类对象中基类部分的引用。只能通过引用改变与其继承的派生类中基类部分的成员。以上程序输出:姓名:Lisi性别:f年龄:26职称:assistant,精选,54,通过本例可以看到:用指向基类对象的指针变量指向子类对象是合法的、安全的,不会出现编译上的错误。但在应用上却不能完全满足人们的希望,人们有时
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 公司自我批评活动方案
- 公司脱口秀比赛活动方案
- 公司每月线上活动方案
- 公司节假日福利策划方案
- 公司本科生团建活动方案
- 公司组织出行活动方案
- 公司秋游爬山活动方案
- 公司盛典活动策划方案
- 公司端午粽子活动方案
- 公司春节营销活动方案
- 《合理使用抗生素》课件
- 数字美的智慧工业白皮书-2023.09
- 桥梁施工进度图
- 某啤酒厂安全现状评价设计报告书模板
- 广西桂林市2022-2023学年高二下学期期末质量检测数学试题(含答案解析)
- 内墙抹灰安全技术交底
- 中学美术校本教材《素描》
- 国开2023年春《理工英语1》机考网考期末复习资料参考答案
- 《幼儿生活活动保育》课程标准
- 年出栏5万头生猪养殖场建设项目及年出栏4800头生猪养殖基地建设项目建议书
- OIF-CEI-04.0OIF-CEI-04.0高速电口标准
评论
0/150
提交评论