2.11.3多(重)继承C++中,从一个基类派生的继承称为单

上传人:t****d 文档编号:243014586 上传时间:2024-09-13 格式:PPT 页数:43 大小:73.50KB
返回 下载 相关 举报
2.11.3多(重)继承C++中,从一个基类派生的继承称为单_第1页
第1页 / 共43页
2.11.3多(重)继承C++中,从一个基类派生的继承称为单_第2页
第2页 / 共43页
2.11.3多(重)继承C++中,从一个基类派生的继承称为单_第3页
第3页 / 共43页
点击查看更多>>
资源描述
,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,2.11.3 多(重)继承,C+中,从一个基类派生的继承称为,单,(一),继承,或。从多个基类派生的继承称为,多,(重),继承,。见下图所示。,类A派生类B 类X和类Y派生类Z,(a) 单继承 (b)多继承,多继承定义,格式:,class派生类名:访问权限 基类名1,访问权限 基类名2,新增加的成员,;,A,B,X,Y,Z,A,B,1,例:build 是一个房屋数据类,buisiness 是建筑单位数据类。以二者为基类按公有方式 派生出工程类proj 。proj 将两个基类的全部成员按原有方式继承下来。,程序清单:,#include,#include,/或,class build,/定义房屋数据类,protected:,int posi_x;,/房屋的经度,int posi_y;,/房屋的纬度,int area;,/房屋的面积,build,business,proj,2,public:,void set1(int x,int y,int a),posi_x=x; posi_y=y; area=a;,;,class business,/定义建筑单位数据类,protected:,char *business_name;,/施工单位,public:,void show(),cout施工单位:business_nameendl;,3,void set2(char *str),strcpy(business_name,str);,;,class proj:public build,public business,private:,int high;,/房屋的高度,public:,void set3(int h),high=h;,4,void disp(),cout经度:posi_xendl;,cout纬度:posi_yendl;,cout高度:highendl;,cout面积:areaendl;,;,void main(),proj obj;,obj.set1(100,200,300);,/调用build类的成员函数,obj.set2(武建集团);,/调用business类的成员函数,obj.set3(400);,/调用proj类的成员函数,obj.disp();,/调用proj类的成员函数,obj.show();,/调用business类的成员函数,5,运行结果:,经度:100,纬度:200,高度:400,面积:300,施工单位:武建集团,C+关于类的继承的规定:, 私有继承方式:基类中的公有成员和保护成员在派生类中皆变为私有成员。, 公有继承方式:基类中的公有成员和保护成员在派生类中不变。, 保护继承方式:基类中的公有成员和保护成员在派生类中皆变为保护成员。, 无论哪种继承方式,私有成员皆不能被继承。,6,当一个类从它的基类中继承一部分成员后,这个类还可以将自己继承的成员再继承给其它的类,这种,继承的可传递性,称作的“,多层继承,”(见下图),与生物繁衍过程的遗传特性十分相似。,图:多层继承示意图,A,B,C,基类,7,2.12 对象引用作函数参数,2.12.1 对象指针作函数参数,使用对象指针作为函数参数要比使用对象作函数参数更为普遍。因为使用,对象指针作函数参数有两点好处,:,实现传址调用,可在被调用函数中改变调用函数的参数对象的值,实现函数之间的信息传递。,使用对象指针实参仅将对象的地址值传给形参,而不进行副本的拷贝,这样,可以提高运行效率,减少时空开销,。,对象指针作函数形参时要求调用函数的实参是对象的地址值(一般用&对象名)。,8,例:指向对象的指针作函数参数的调用方法分析程序输出结果。,/obj_ptr.cpp,#include,class M,public:,M()x=y=0;,M(int i,int j)x=i; y=j;,void copy(M *m);,void setxy(int i,int j)x=i; y=j;,void print()coutx,yx;,y=m-y;,void fun(M m1,M *m2),/m1:对象名作形参,m2:对象指针名作形参,m1.setxy(12,15);,m2-setxy(22,25);,void main(),M p(5,7),q;,q.copy(,fun(p,p.print();,q.print();,10,运行结果:,5,7,22,25,实参用对象地址值:,&对象名,,形参用指向对象的指针名。,1.3.句执行情况:,1.M p(5,7),q;,p.x=5,p.y=7;q.x=0,q.y=0.,2.q.copy(,q.x=5,q.y=7;,3.fun(p,q.x=22,q.y=25;,11,2.12.2 对象引用作函数参数,在实际工作中,使用对象引用作函数参数比使用对象指针作函数参数更普遍。这是因为使用对象引用作函数参数具有对象指针作函数参数的优点,并且用对象引用作函数参数将更简单、更直接。因此,C+程序员喜欢用对象引用作函数参数。,例:分析下面程序输出结果。,/obj_ref.cpp,#include,class M,public:,M()x=y=0;,M(int i,int j)x=i; y=j;,void copy(M ,12,void setxy(int i,int j)x=i; y=j;,void print()coutx,yendl;,private:,int x,y;,;,void M:copy(M &m),x=m.x;,y=m.y;,13,void M:copy(M &m),x=m.x;,y=m.y;,void fun(M m1,M &m2),m1.setxy(12,15);,m2.setxy(22,25);,14,void main(),M p(5,7),q;,q.copy(p);,fun(p,q);,p.print();,q.print();,运行结果(与上例相同):,5,7,22,25,实参用对象名,形参用对象引用名。,说明:本例程序与前面程序主要区别在于把使用指向对象的指针换成了对象引用。试比较一下指针与引用在使用上的区别。,15,2.13 this指针,this是隐含于每一个类的成员函数中的特殊指针。,简言之,,this是指向“当前对象”的指针,。通过该指针可以确定哪个对象的成员被引用。,每次成员函数存取数据成员时,则隐含使用this指针。同样也可使用,*this,来标识调用该成员函数的对象。,例:显示this指针的值。,程序清单:,#include,class A,private:,int x, y;,public:,16,A(int i,int j), x=i;,y=j;,void get(),coutnthis=,this, when x=xendl;,;,void main(), A a(1,1),b(2,2),c(3,3);,a.get();,b.get();,c.get();,17,运行结果:,this=0x0065FDF0 when x=1 /a对象的地址,this=0x0065FDE8 when x=2 /b对象的地址,this=0x0065FDE0 when x=3 /c对象的地址,例:分析下列程序输出结果,说明程序中this和*this的用法。,程序清单:,#include,class A,public:,A() a=b=0;,A(int i,int j) a=i;b=j;,void copy(A ,18,void print(),couta,ba=aa.a; this-b=aa.b;,19,void main(),A a1,a2(3,4);,/1.,a1.copy(a2);,/2.,a1.print();,/3.,运行结果:,3,4,分析:,本程序中,this是操作该成员函数对象的地址 ;*this是操作该成员函数的对象,而,*this=aa;/,*this:this所指向的对象,它表示将形参获得的某对象的值赋给操作该成员函数的对象。在本例中,操作该成员函数的对象为a1。,20,1.3.句执行的情况:,1.a1.a=0,a1.b=0;,a2.a=3,a2.b=4;,2. (1) aa.a=3,aa.b=4;,(2) if(this=,this=&a1,&aa=&a2,故this&aa(条件不满足,执行后续语句),(3) *this=aa;,aa.aa1.a, aa.ba1.b,3.显示a1.a和a1.b;,21,2.14 多态性,多态性,(,polymorphism,)是,指一个接口的名称具有多种功能,。在面向对象的三大基本特征中,封装性是基础,继承性是关键,多态性是补充。,多态性有两种类型:1、,重载,(,函数重载,,运算符/,操作符重载,),2、,虚拟函数,重载(,overloading,:包括函数重载和操作符重载)属于程序编译时的多态性;虚拟函数(,virtual function,)属于程序运行时的多态性。,2.14.1 函数重载,函数重载,(,function overloading,)是,指两个或两个以上的函数取相同的名字,而使用不同类型或不同数目的参数,。,使用函数重载可以减轻用户的记忆负担,并使程序结构简单、易懂。,C+的构造器可以重载,另外,用户还可在程序中定义其它重载函数。,例:P69,例Ex_OverLoad, 编程求两个或三个操作数之和。,22,2.14.2 操作符重载,操作符重载,(,operator overloading,)是,指将已有的操作符/运算符赋予新的功能,。,可把操作符重载看成类的成员函数,称为操作符重载成员函数。,操作符重载成员函数,定义格式,:,类型类名:operator操作符(参数表),函数体,其中,operator是用于定义操作符重载函数的关键词。操作符重载成员函数定义在类内时,类名:省略不写。,C+中,操作符可以是三种通用的操作符:算术运算符、逻辑运算符和位运算符。可以将所有的三种类型的操作符重载,让它们去完成程序员需要的动作而取代其默认情况下的操作。,23,例:重载“+”运算符实现两个时间相加。,程序清单:,#include,class Mytime,private:,int hour;,int min;,int sec;,public:,Mytime(),hour=min=sec=0;,/构造器1,24,Mytime(int h1,int m1,int s1),sec=s1%60;,m1=m1+s1/60;,min=m1%60;,h1=h1+m1/60;,hour=h1%24;,/构造器2(将时、分、秒转换成相应进制的数),Mytime operator+(Mytime T1),Mytime T2(hour+T1.hour,min+T1.min,sec+T1.sec);,return T2;,/操作符重载成员函数,25,void PrintMytime(),coutTime:;,couthour;,cout:min;,cout:sechour, min等价于this-min, sec等价于this-sec;而执行此句时,this指向t1对象,故:hour实为t1.hour,min实为t1.min,sec实为t1.sec;,相加后:T2(7,55,67);,执行构造器2后:T2(7,56,7),构造器2所完成的功能:将分和秒转换成60以内的数,将小时转换成24以内的数。,(3),执行return T2;,返回T2传给主函数t3。,28,不能重载的操作符有:,:?三目操作符,.成员运算符,:作用域操作符,-指向运算符,sizeof()sizeof()运算符,29,例:用操作符重载成员函数编写,和,两向量相加的程序。,/ex_opovld.cpp:运算符重载为类的成员函数,#include,class V_sum,private:,float x,y;,public:,V_sum(),x=y=0;,30,V_sum(float a,float b),x=a; y=b;,V_sum operator+(V_sum u1);,/运算符重载为类的成员函数,形参个数比运算符操作数个数少一个,void V_output();,;,V_sum V_sum:operator+(V_sum u1),V_sum u2(this-x+u1.x,this-y+u1.y);,return u2;,31,void V_sum:V_output(),coutV3=(x,y)endl;,void main(),V_sum V1(1,5),V2(8,3),V3;,V3=V1+V2;,/编译器将V1+V2解释成V1.operator+(V2),V3.V_output();,32,2.14.3 虚函数,虚函数,(,virtual function,)是,指某个函数在基类中被定义为virtual,而在派生类中又重新定义了该函数,。,虚函数是实现动态联编的基础。,联编是指一个计算机程序自身彼此关联的过程。按照联编所进行的阶段不同,可分为两种联编方法:静态联编和动态联编。,程序在编译时进行联编工作被称为,静态联编,,或称为静态束定。,程序在运行时进行联编工作被称为,动态联编,,或称为动态束定。,虚函数定义,格式:,virtual 函数类型 函数名(参数表),函数体,虚函数必须存在于继承的环境中,。,33,程序例:,#include,class cA,/定义基类,public:,double A(double x),return x*x;,double B(double x),return A(x)/2;,;,34,class cB:public cA,/定义cA的派生类,public:,double A(double x),return x*x*x;,;,void main(),cB obj;,coutobj.B(3)endl;,35,运行结果:,4.5(而不是13.5?),意图:cA:B CALL cB:A,实际:cA:B CALL cA:A,而cB:A弃而不用,注:cA:BcA类继承下来的函数B,cB:A类cB中的函数A,该程序的输出是4.5,而不是13.5!为什么?回答是基于这样一个事实,那就是程序执行obj. B(3)时使用的是继承函数cA:B,而接下来cA:B调用的却是函数cA:A。这样函数cB:A被搁置在一边弃而不用,程序未能支持多态性的行为。,36,例:现在上例的类cA和类cB的A函数前加virtual,重写程序(该程序表明虚函数是怎样成功地在类cA和类cB中完成多态性行为的)。,#include,class cA/定义基类,public:,/定义虚函数,在基类中必须加关键词virtual,virtual,double A(double x),return x*x;,double B(double x),return A(x)/2;,;,37,运行结果:,13.5,cA:B CALL cB:A,(从类cA继承下来的函数B调用类cB中定义的函数A),一旦说明一个函数是虚函数,则只能用子孙类中的函数来超越。超越和被超越的函数必须相同的参数表和返回类型。,虚函数的特性,:,一旦为虚总为虚,(即,虚函数具有继承性,)。,例:教材P87,例Ex_VirtClass,。,38,2.15 友元函数,类的重要特性是使数据封装与隐藏,但同时也给外部函数访问类中的私有和保护数据成员带来了不便,为此,C+提供了友元函数来解决这个问题。,友元函数,(,friend function,:简称友元),可以存取类的私有成员、保护成员和公有成员,。,类的友元函数是类的接口的一部分,但它不是类的成员函数,因此没有this指针。,友元函数定义,格式:,法1:类内定义,friend 类型 函数名(参数表),函数体,39,法:类外定义,(1) 类内说明友元函数,friend类型函数名(参数表);,(2) 类外定义友元函数(与一般函数定义格式相同),类型函数名(参数表),函数体,例:友元函数示例P89,例Ex_Friend,。,操作符即可重载为成员函数,也可重载为友元函数。,操作符重载友元函数,说明格式:,friend类型operator操作符(参数表);,40,例:用操作符重载友元函数编写,和,两向量相加的程序。,#include,class V_sum,private:,float x,y;,public:,V_sum(),x=y=0;,V_sum(float a,float b),x=a; y=b;,41,friend V_sum operator+(V_sum u1,V_sum u2);,/操作符重载为友元函数,形参个数与运算符操作数个数相同(教材第行),void V_output();,;,V_sum operator+(V_sum u1,V_sum u2),float a=u1.x+u2.x;,float b=u1.y+u2.y;,return V_sum(a,b);,void V_sum:V_output(),coutV3=(x,y)endl;,42,void main(),V_sum V1(1,5),V2(8,3),V3;,V3=,V1+V2,;/编译器将V1+V2解释成operator+(V1,V2),V3.V_output();,需强调说明的是:当操作符重载为类的友元函数,形参个数与操作符操作数个数相同(教材第行);当操作符重载为类的成员函数时,操作符重载函数的形参个数要比操作符操作数个数少一个(教材P91页12行)。,43,
展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 图纸专区 > 大学资料


copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!