C++实用教程[郑阿奇主编]12ppt课件_第1页
C++实用教程[郑阿奇主编]12ppt课件_第2页
C++实用教程[郑阿奇主编]12ppt课件_第3页
C++实用教程[郑阿奇主编]12ppt课件_第4页
C++实用教程[郑阿奇主编]12ppt课件_第5页
已阅读5页,还剩50页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

.,第12章继承和派生,.,12.1继承和派生概述,12.1.1继承的概念1.继承和概括继承(Inheritance),是指一个事物可以继承其父辈全部或部分特性,同时本身还有自己的特性。2.类继承相关概念在C+中,当一个新类从一个已定义的类中派生后,新类不仅继承了原有类的属性和方法,并且还拥有自己新的属性和方法,称为类的继承和派生。被继承的类称为基类(Baseclass)或超类(Superclass)(又称父类),在基类或父类上建立的新类称为派生类(Derivedclass)或子类(Subclass)。,.,3.类层次关系的描述方法上述父类和子类的关系称为类层次或继承关系。在类设计时,常常将这些关系用树来描述。例如,下图就是用树来描述学校人员类的层次关系。,.,12.1.2继承的特性,在C+中,类的继承具有下列特性:(1)单向性。(2)传递性。(3)可重用性。12.1.3派生类的定义在C+中,一个派生类的定义可按下列格式:class:,;,.,12.2继承方式,C+继承方式有三种:public(公有)、private(私有)及protected(保护)12.2.1公有继承公有继承(public)方式具有下列特点:(1)在派生类中,基类的公有成员、保护成员和私有成员的访问属性保持不变。(2)派生类对象只能访问派生类和基类的公有(public)成员。,.,例Ex_PublicDerived派生类的公有继承示例。,#include#includeusingnamespacestd;classCPersonpublic:CPerson(char*name,intage,charsex=M)strncpy(this-name,name,20);this-age=age;this-sex=sex;voidSetNameAndSex(char*name,charsex=M)/更改姓名和性别strncpy(this-name,name,20);this-sex=sex;protected:,.,voidSetAge(intage)this-age=age;voidShowInfo()/显示信息cout姓名:nameendl;cout性别:(sex=M?男:女)endl;cout年龄:agestuno,no,20);this-SetAge(age);voidShowAll()ShowInfo();/调用基类的成员函数cout学号:stunoendl;cout三门成绩:score0tscore1tscore2endl;cout总成绩和平均分:totaltaveage=age;this-sex=sex;voidSetNameAndSex(char*name,charsex=M)/更改姓名和性别strncpy(this-name,name,20);this-sex=sex;protected:,.,voidSetAge(intage)this-age=age;voidShowInfo()/显示信息cout姓名:nameendl;cout性别:(sex=M?男:女)endl;cout年龄:agestuno,no,20);this-SetAge(age);voidShowAll()ShowInfo();/调用基类的保护成员函数cout学号:stunoendl;cout三门成绩:score0tscore1tscore2endl;cout总成绩和平均分:totaltaveendl;/修改的代码,.,voidSetNameAndSex(char*name,charsex=M)/更改姓名和性别CPerson:SetNameAndSex(name,sex);/调用基类的公有成员函数private:charstuno20;/学号floatscore3,ave,total;/三门成绩、平均分和总分;intmain()CStudentone(LiMing,21050101,19);one.SetScore(90,80,84);one.ShowAll();one.SetNameAndSex(WangFang,W);one.SetNoAndAge(21050102,18);one.ShowAll();return0;程序运行结果同前。,.,12.2.3保护继承,保护继承(protected)方式具有下列特点:(1)在派生类中,基类的公有成员、保护成员的访问属性都将变成保护的。(2)同私有继承一样,在保护继承方式下,派生类中仍可访问基类的公有成员和保护成员。,.,12.3派生类的构造和析构12.3.1构造和析构次1.单继承如图12.2(a)所示,A类是B类的基类,B类又是C类的基类,它们是多层单继承方式其代码如下:,.,classApublic:A()cout执行A的构造函数endl;A()cout执行A的析构函数endl;classB:publicApublic:B()cout执行B的构造函数endl;B()cout执行B的析构函数endl;classC:publicB,.,public:C()cout执行C的构造函数endl;C()cout执行C的析构函数endl;intmain()Cc;return0;程序运行结果如下,.,2.多继承如图12.2(b)所示,类A和类B是C类的基类,它们是多继承方式,其代码如下:,classApublic:A()cout执行A的构造函数endl;A()cout执行A的析构函数endl;classBpublic:B()cout执行B的构造函数endl;B()cout执行B的析构函数endl;classC:publicB,publicA,.,public:C()cout执行C的构造函数endl;C()cout执行C的析构函数endl;intmain()Cc;return0;程序运行结果如下:执行B的构造函数执行A的构造函数执行C的构造函数执行C的构造函数执行A的构造函数执行B的构造函数,.,12.3.2派生类数据成员初始化,一个派生类的构造函数的定义可有下列格式:(形参表):基类1(参数表),基类2(参数表),基类n(参数表),对象成员1(参数表),对象成员2(参数表),对象成员n(参数表),例如,一个长方体类CCuboid,它从基类矩形类CRect派生而来。基类CRect的数据成员是两个CPoint类对象ptLT和ptRB,分别表示矩形的左上角点和右下角点的位置。派生类CCuboid自身的数据成员有表示高度的fHeight,表示底面中点位置的CPoint对象ptCenter,如右图所示。具体程序如下。,.,例Ex_ClassDerived派生类的构造和析构示例。,#includeusingnamespacestd;classCPointpublic:CPoint(intx=0,inty=0)/CxPos=x;yPos=y;coutCPoint构造函数endl;voidShowPos(boolisEnd=false)coutpos(xPos,yPos);if(isEnd)coutendl;private:intxPos,yPos;,.,classCRectpublic:CRect(intx1=0,inty1=0,intx2=0,inty2=0)/B:ptLT(x1,y1),ptRB(x2,y2)coutCRect构造函数endl;voidShowPos()ptLT.ShowPos();cout,;ptRB.ShowPos(true);private:CPointptLT,ptRB;,.,classCCuboid:publicCRectpublic:CCuboid(intx1,inty1,intx2,inty2,intheight)/A:CRect(x1,y1,x2,y2),ptCenter(x1+x2)/2,(y1+y2)/2),fHeight(height)coutCCuboid构造函数endl;voidShowAll()cout矩形的角点为:;CRect:ShowPos();cout底面矩形的中点为:;ptCenter.ShowPos(true);cout高为:fHeightendl;,.,private:CPointptCenter;floatfHeight;intmain()CCuboidone(5,5,30,30,50);one.ShowAll();return0;程序运行结果如下:,.,12.4二义性和虚基类,12.4.1二义性概述一般来说,在派生类中对基类成员的访问应该是唯一的。但是多继承或多层继承可能造成对基类中某成员的访问出现不唯一的情况,这种情况称为基类成员调用的二义性。二义性出现的情况可以有下列两种。1.同名成员来源于不同的基类例Ex_Conflict1同名成员来源于不同的基类,.,#includeusingnamespacestd;classApublic:intx;A(inta=0)x=a;classBpublic:intx;B(inta=0,intb=0)x=a;classC:publicB,publicA,.,public:intz;C(inta,intb,intc):A(a),B(b)z=c;voidprint()coutx=xendl;/编译出错的地方coutz=zendl;intmain()Cc1(100,200,300);c1.print();return0;,.,程序中,派生类C同时继承了A和B这两个基类,由于基类A和基类B都有数据成员x,当编译到“coutx=xendl;”语句时,无法确定成员x是来自基类A还是来自基类B,因此产生了二义性,从而出现编译错误。解决这个问题的简单方法是使用域作用运算符“:”来消除二义性,即将print函数实现代码改为:,voidprint()coutA:x=A:xendl;coutB:x=B:xendl;coutz=zendl;重新运行的结果如下,.,2.同名成员来源于同一个基类,例Ex_Conflict2同名成员来源于同一个基类。#includeusingnamespacestd;classApublic:intx;A(inta=0)x=a;classB1:publicApublic:inty1;B1(inta=0,intb=0):A(b)y1=a;,.,classB2:publicApublic:inty2;B2(inta=0,intb=0):A(b)y2=a;classC:publicB1,publicB2public:intz;C(inta,intb,intd,inte,intm):B1(a,b),B2(d,e)z=m;,.,voidprint()coutx=xendl;/编译出错的地方couty1=y1,y2=y2endl;coutz=zendl;intmain()Cc1(100,200,300,400,500);c1.print();return0;程序中,B1类和B2类都是从基类A继承的派生类,这时在继承B1和B2的派生类C中就有两个基类A的拷贝。当编译器编译到“coutx=xendl;”语句时,因无法确定成员x是从类B1中继承来的,还是从类B2继承来的,因此产生二义性,从而出现了编译错误。解决这个问题仍可使用前面的方法,即使用域作用运算符“:”通过指定基类来消除二义性。例如,可将print函数实现代码改写为,.,voidprint()coutB1:x=B1:xendl;coutB2:x=B2:xendl;couty1=y1,y2=y2endl;coutz=zendl;重新运行后的结果如下:,.,12.4.2二义性解决方法,(1)当派生类和其基类中都有一个成员X时,在派生类中访问的X就是派生类的成员X,这是C+中类的局部优先原则。(2)若A类是B类的基类,B类是C类的基类,当A类和B类都有一个成员X时,则在子类C中访问的X是B类的成员,这是C+中类的最近优先原则。对于出现二义性的第1种情况,指定作用域是最好的解决方法。但对于第2种情况,指定作用域虽是一种解决方法,但不是最好的办法。因为在派生类C中总有两个基类A的拷贝,不仅多占用内存,而且效率也不高。为此在实际应用中多采用虚基类的形式来解决。,.,12.4.3虚基类和虚继承,1.虚基类的定义虚基类不是指基类是虚的,而是指在派生类中指定的基类是虚继承方式,即使用下列格式定义派生类的继承方式:class:virtual;例Ex_VirtualBase虚基类的使用示例。,.,#includeusingnamespacestd;classApublic:intx;A(inta=0)x=a;classB1:virtualpublicA/声明虚继承public:inty1;B1(inta=0,intb=0):A(b)y1=a;voidprint(void)coutB1:x=x,y1=y1endl;,.,classB2:virtualpublicA/声明虚继承public:inty2;B2(inta=0,intb=0):A(b)y2=a;voidprint(void)coutB2:x=x,y2=y2endl;classC:publicB1,publicB2public:intz;C(inta,intb,intd,inte,intm):B1(a,b),B2(d,e)z=m;,.,voidprint()B1:print();B2:print();coutz=zendl;intmain()Cc1(100,200,300,400,500);c1.print();c1.x=400;c1.print();return0;程序运行结果如下:,.,2.虚基类的实质在上述示例中,类A、B1、B2和C的层次关系可用图12.5来表示,图12.5类的层次关系,.,12.5兼容,兼容是指在公有派生情况下,一个派生类对象可以赋给基类对象,这种情况又称为赋值兼容,或称类型自动转换。12.5.1赋值兼容规则简单地讲,对于公有派生类来说,可以将派生类的对象直接赋给其基类对象,反之却不可以。12.5.2赋值兼容机理例Ex_CastTest派生类赋值兼容测试示例。,.,#include#includeusingnamespacestd;classCApublic:CA(intx=0)a=x;intgetA()returna;private:inta;classCBpublic:CB(intx=0)b=x;intgetB()returnb;private:intb;classCC:publicCB,publicCA,.,public:CC(inty=0)c=y;intgetC()returnc;private:intc;intmain()CC*c=newCC(5);coutgetC()getB()getA()getC()getB()getA()endl;deletec;return0;程序运行结果如下:,.,Ex_CastOther派生类赋值兼容其他情况示例。,#include#includeusingnamespacestd;classCApublic:CA(intx=0)a=x;intgetA()returna;voidShowAddr()coutCA对象的地址:(unsigned)thisendl;coutta的地址:(unsigned)classCB,.,public:CB(intx=0)b=x;intgetB()returnb;voidShowAddr()coutCB对象的地址:(unsigned)thisendl;couttb的地址:(unsigned),.,private:intc;intmain()CCc(5);/c对象中的数据成员c为5coutShowAddr();coutage=age;this-sex=sex;,.,v

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论