收藏 分销(赏)

C++实用教程[郑阿奇主编]12ppt课件.ppt

上传人:二*** 文档编号:12603843 上传时间:2025-11-10 格式:PPT 页数:55 大小:176KB 下载积分:5 金币
下载 相关 举报
C++实用教程[郑阿奇主编]12ppt课件.ppt_第1页
第1页 / 共55页
本文档共55页,全文阅读请下载到手机保存,查看更方便
资源描述
单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,.,*,第12章 继承和派生,.,12.1 继承和派生概述,12.1.1 继承的概念,1.继承和概括,继承(Inheritance),是指一个事物可以继承其父辈全部或部分特性,同时本身还有自己的特性。,2.类继承相关概念,在C+中,当一个新类从一个已定义的类中派生后,新类不仅继承了原有类的属性和方法,并且还拥有自己新的属性和方法,称为类的继承和派生。被继承的类称为基类(Base class)或超类(Super class)(又称父类),在基类或父类上建立的新类称为派生类(Derived class)或子类(Sub class)。,.,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,#include,using namespace std;,class CPerson,public:,CPerson(char*name,int age,char sex=M),strncpy(this-name,name,20);,this-age=age;this-sex=sex;,void SetNameAndSex(char*name,char sex=M)/更改姓名和性别,strncpy(this-name,name,20);this-sex=sex;,protected:,.,void SetAge(int age),this-age=age;,void ShowInfo()/显示信息,cout姓名:nameendl;,cout性别:(sex=M?男:女)endl;,cout年龄:agestuno,no,20);,void SetScore(float s1,float s2,float s3),score0=s1;score1=s2;score2=s3;,total=s1+s2+s3;ave=total/(float)3.0;,void SetNoAndAge(char*no,int age),strncpy(this-stuno,no,20);this-SetAge(age);,void ShowAll(),ShowInfo();/调用基类的成员函数,cout学号:stunoendl;,cout三门成绩:score0tscore1tscore2endl;,cout总成绩和平均分:totaltavename,name,20);,this-age=age;this-sex=sex;,void SetNameAndSex(char*name,char sex=M),/更改姓名和性别,strncpy(this-name,name,20);this-sex=sex;,protected:,.,void SetAge(int age),this-age=age;,void ShowInfo()/显示信息,cout姓名:nameendl;,cout性别:(sex=M?男:女)endl;,cout年龄:agestuno,no,20);,public:,void SetScore(float s1,float s2,float s3),score0=s1;score1=s2;score2=s3;,total=s1+s2+s3;ave=total/(float)3.0;,void SetNoAndAge(char*no,int age),strncpy(this-stuno,no,20);this-SetAge(age);,void ShowAll(),ShowInfo();/调用基类的保护成员函数,cout学号:stunoendl;,cout三门成绩:score0tscore1tscore2endl;,cout总成绩和平均分:totaltaveendl;,/修改的代码,.,void SetNameAndSex(char*name,char sex=M)/更改姓名和性别,CPerson:,SetNameAndSex(name,sex);/调用基类的公有成员函数,private:,charstuno20;/学号,floatscore3,ave,total;,/三门成绩、平均分和总分,;,int main(),CStudent one(LiMing,21050101,19);,one.SetScore(90,80,84);,one.ShowAll();,one.SetNameAndSex(WangFang,W);,one.SetNoAndAge(21050102,18);,one.ShowAll();,return 0;,程序运行结果同前。,.,12.2.3 保护继承,保护继承(protected)方式具有下列特点:,(1)在派生类中,基类的公有成员、保护成员的访问属性都将变成保护的。,(2)同私有继承一样,在保护继承方式下,派生类中仍可访问基类的公有成员和保护成员。,.,12.3 派生类的构造和析构,12.3.1 构造和析构次 1.单继承,如图12.2(a)所示,A类是B类的基类,B类又是C类的基类,它们是多层单继承方式,其代码如下:,.,class A,public:,A()cout执行A的构造函数endl;,A()cout执行A的析构函数endl;,;,class B:public A,public:,B()cout执行B的构造函数endl;,B()cout执行B的析构函数endl;,;,class C:public B,.,public:,C()cout执行C的构造函数endl;,C()cout执行C的析构函数endl;,;,int main(),C c;,return 0;,程序运行结果如下,.,2.多继承如图12.2(b)所示,类A和类B是C类的基类,它们是多继承方式,其代码如下:,class A,public:,A()cout执行A的构造函数endl;,A()cout执行A的析构函数endl;,;,class B,public:,B()cout执行B的构造函数endl;,B()cout执行B的析构函数endl;,;,class C:,public B,public A,.,public:,C()cout执行C的构造函数endl;,C()cout执行C的析构函数endl;,;,int main(),C c;,return 0;,程序运行结果如下:,执行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,派生类的构造和析构示例。,#include,using namespace std;,class CPoint,public:,CPoint(int x=0,int y=0)/,C,xPos=x;yPos=y;,coutCPoint构造函数endl;,void ShowPos(bool isEnd=false),coutpos(xPos,yPos);,if(isEnd)coutendl;,private:,int xPos,yPos;,;,.,class CRect,public:,CRect(int x1=0,int y1=0,int x2=0,int y2=0),/B,:ptLT(x1,y1),ptRB(x2,y2),coutCRect构造函数endl;,void ShowPos(),ptLT.ShowPos();cout,;ptRB.ShowPos(true);,private:,CPoint ptLT,ptRB;,;,.,class CCuboid:,public CRect,public:,CCuboid(int x1,int y1,int x2,int y2,int height),/A,:CRect(x1,y1,x2,y2),ptCenter(x1+x2)/2,(y1+y2)/2),fHeight(height),coutCCuboid构造函数endl;,void ShowAll(),cout矩形的角点为:;CRect:ShowPos();,cout底面矩形的中点为:;ptCenter.ShowPos(true);,cout高为:fHeightendl;,.,private:,CPointptCenter;,floatfHeight;,;,int main(),CCuboid one(5,5,30,30,50);,one.ShowAll();,return 0;,程序运行结果如下:,.,12.4 二义性和虚基类,12.4.1 二义性概述,一般来说,在派生类中对基类成员的访问应该是唯一的。但是多继承或多层继承可能造成对基类中某成员的访问出现不唯一的情况,这种情况称为基类成员调用的二义性。,二义性出现的情况可以有下列两种。,1.同名成员来源于不同的基类,例,Ex_Conflict1,同名成员来源于不同的基类,.,#include,using namespace std;,class A,public:,int x;,A(int a=0)x=a;,;,class B,public:,int x;,B(int a=0,int b=0)x=a;,;,class C:,public B,public A,.,public:,int z;,C(int a,int b,int c),:A(a),B(b),z=c;,void print(),coutx=xendl;,/,编译出错的地方,coutz=zendl;,;,int main(),C c1(100,200,300);,c1.print();,return 0;,.,程序中,派生类,C,同时继承了,A,和,B,这两个基类,由于基类,A,和基类,B,都有数据成员,x,,当编译到“,coutx=xendl;”,语句时,无法确定成员,x,是来自基类,A,还是来自基类,B,,因此产生了二义性,从而出现编译错误。解决这个问题的简单方法是使用域作用运算符“:”来消除二义性,即将print函数实现代码改为:,void print(),coutA:x=A:xendl;,coutB:x=B:xendl;,coutz=zendl;,重新运行的结果如下,.,2.同名成员来源于同一个基类,例,Ex_Conflict2,同名成员来源于同一个基类。,#include,using namespace std;,class A,public:,int x;,A(int a=0)x=a;,;,class B1:public A,public:,int y1;,B1(int a=0,int b=0),:A(b),y1=a;,;,.,class B2:public A,public:,int y2;,B2(int a=0,int b=0),:A(b),y2=a;,;,class C:public B1,public B2,public:,int z;,C(int a,int b,int d,int e,int m),:B1(a,b),B2(d,e),z=m;,.,void print(),coutx=xendl;/编译出错的地方,couty1=y1,y2=y2endl;,coutz=zendl;,;,int main(),C c1(100,200,300,400,500);,c1.print();,return 0;,程序中,,B1,类和,B2,类都是从基类,A,继承的派生类,这时在继承,B1,和,B2,的派生类,C,中就有两个基类,A,的拷贝。当编译器编译到“,coutx=xendl;”,语句时,因无法确定成员,x,是从类,B1,中继承来的,还是从类,B2,继承来的,因此产生二义性,从而出现了编译错误。,解决这个问题仍可使用前面的方法,即使用域作用运算符“:”通过指定基类来消除二义性。例如,可将print函数实现代码改写为,.,void print(),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,虚基类的使用示例。,.,#include,using namespace std;,class A,public:,int x;,A(int a=0)x=a;,;,class B1:virtual public A/声明虚继承,public:,int y1;,B1(int a=0,int b=0),:A(b),y1=a;,void print(void),coutB1:x=x,y1=y1endl;,;,.,class B2:virtual public A/声明虚继承,public:,int y2;,B2(int a=0,int b=0),:A(b),y2=a;,void print(void),coutB2:x=x,y2=y2endl;,;,class C:public B1,public B2,public:,int z;,C(int a,int b,int d,int e,int m),:B1(a,b),B2(d,e),z=m;,.,void print(),B1:print();B2:print();,coutz=zendl;,;,int main(),C c1(100,200,300,400,500);c1.print();,c1.x=400;c1.print();,return 0;,程序运行结果如下:,.,2.虚基类的实质,在上述示例中,类A、B1、B2和C的层次关系可用图12.5来表示,图12.5 类的层次关系,.,12.5 兼容,兼容是指在公有派生情况下,一个派生类对象可以赋给基类对象,这种情况又称为赋值兼容,或称类型自动转换,。,12.5.1 赋值兼容规则,简单地讲,对于公有派生类来说,可以将派生类的对象直接赋给其基类对象,反之却不可以。12.5.2 赋值兼容机理,例,Ex_CastTest,派生类赋值兼容测试示例。,.,#include,#include,using namespace std;,class CA,public:,CA(int x=0)a=x;,int getA()return a;,private:,int a;,;,class CB,public:,CB(int x=0)b=x;,int getB()return b;,private:,int b;,;,class CC:public CB,public CA,.,public:,CC(int y=0)c=y;,int getC()return c;,private:,int c;,;,int main(),CC*c=new CC(5);,coutgetC()getB()getA()endl;,CA a(3);,CB b(4);,memcpy(CA,*,)c,/A,memcpy(CB,*,)c,/B,coutgetC()getB()getA()endl;,delete c;,return 0;,程序运行结果如下:,.,Ex_CastOther,派生类赋值兼容其他情况示例。,#include,#include,using namespace std;,class CA,public:,CA(int x=0)a=x;,int getA()return a;,void ShowAddr(),coutCA对象的地址:(unsigned)thisendl;,coutta的地址:(unsigned),private:,int a;,;,class CB,.,public:,CB(int x=0)b=x;,int getB()return b;,void ShowAddr(),coutCB对象的地址:(unsigned)thisendl;,couttb的地址:(unsigned),private:,int b;,;,class CC:public CB,public CA,public:,CC(int y=0)c=y;,int getC()return c;,void ShowAddr(),CA:ShowAddr();,CB:ShowAddr();,coutCC对象的地址:(unsigned)thisendl;,couttc的地址:(unsigned),.,private:,int c;,;,int main(),CC c(5);/c对象中的数据成员c为5,cout-CC c(5);-endl;,c.ShowAddr();,coutShowAddr();,cout-CB,CB/B,b.ShowAddr();,b=CB(4);,*a=CA(3);,coutc.getC(),c.getB(),c.getA()name,name,20);,this-age=age;this-sex=sex;,.,void ShowInfo()/显示信息,cout姓名:nameendl;,cout性别:(sex=M?男:女)endl;,cout年龄:ageclassname,strname,20);,strncpy(this-stuno,stuno,20);,score0=s1;score1=s2;score2=s3;,total=s1+s2+s3;ave=total/(float)3.0;,void ShowInfo(),cout班级:classnameendl;,cout学号:stunoendl;,cout三门成绩:score0tscore1tscore2endl;,cout总成绩和平均分:totaltavetitle,title,20);strncpy(this-part,part,20);,this-workyears=years;,void ShowInfo(),cout职称:titleendl;,cout部门:partendl;,cout工龄:workyearsduty,duty,20);,tutor.SetData(title,part,years);,.,void ShowInfo(),cout导师信息:endl;,tutor.ShowInfo();,cout职责:dutyendl;,private:,CTeachertutor;,charduty20;/职责,;,int main(),CAssistant one(DING,38,M,WANG,19);,one.SetData(批改作业,教授,机电学院,15);,one.CStudent:SetData(机电班,210101,80,90,80);,one.CTeacher:SetData(助课,机电学院,2);,one.CTeacher:ShowInfo();,one.CStudent:ShowInfo();,one.ShowInfo();,return 0;,.,程序运行结果如下:,.,
展开阅读全文

开通  VIP会员、SVIP会员  优惠大
下载10份以上建议开通VIP会员
下载20份以上建议开通SVIP会员


开通VIP      成为共赢上传

当前位置:首页 > 教育专区 > 初中其他

移动网页_全站_页脚广告1

关于我们      便捷服务       自信AI       AI导航        抽奖活动

©2010-2025 宁波自信网络信息技术有限公司  版权所有

客服电话:0574-28810668  投诉电话:18658249818

gongan.png浙公网安备33021202000488号   

icp.png浙ICP备2021020529号-1  |  浙B2-20240490  

关注我们 :微信公众号    抖音    微博    LOFTER 

客服