




免费预览已结束,剩余43页可下载查看
下载本文档
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第8章多态性,8.1运算符重载8.2运算符重载为类的成员函数8.3运算符重载为类的友元函数8.4虚函数,8.1运算符重载,8.1.1问题的提出例6.3的复数类#includeiostream.hclassCComplexprivate:doublereal;doubleimag;public:CComplex(doubler,doublei);voidPrint();CComplexAdd(CComplexc);CComplexSub(CComplexc);,第8章多态性,CComplexCComplex:Add(CComplexc)CComplextemp;temp.real=real+c.real;temp.imag=imag+c.imag;returntemp;CComplexCComplex:Sub(CComplexc)CComplextemp;temp.real=real-c.real;temp.imag=imag-c.imag;returntemp;,8.1运算符重载,8.1.1问题的提出(续一)voidmain(void)CComplexa(1,2),b(3.0,4.0),c,d;c=a.Add(b);d=a.Sub(b);coutc=;c.Print();coutd=;d.Print();,第8章多态性,运算符重载:运算符重载的实质就是对已有的运算符赋予多重含义,使同一个运算符作用于不同类型的数据时,产生不同的行为。运算符重载的实质就是函数重载。,例8.1用运算符实现复数的加减运算,#includeiostream.hclassCComplexprivate:doublereal;doubleimag;public:CComplex(doubler=0,doublei=0);voidPrint();CComplexoperator+(CComplexc);CComplexoperator-(CComplexc);CComplex:CComplex(doubler,doublei)real=r;imag=i;,第8章多态性,例8.1(续一),voidCComplex:Print()cout(real,imag)endl;CComplexCComplex:operator+(CComplexc)CComplextemp;temp.real=real+c.real;temp.imag=imag+c.imag;returntemp;CComplexCComplex:operator-(CComplexc)CComplextemp;temp.real=real-c.real;temp.imag=imag-c.imag;returntemp;,第8章多态性,例8.1(续二),voidmain(void)CComplexa(1,2),b(3.0,4.0),c,d;c=a+b;d=a-b;coutc=;c.Print();coutd=;d.Print();,第8章多态性,该语句相当于对函数operator+(CComplexc)的调用:“c=a.operator+(b)”,实现两个复数的加法运算。,程序运行结果为:c=(4,6)d=(-2,-2),8.1运算符重载,8.1.2运算符重载的格式与规则1.运算符重载的格式运算符重载为类的成员函数运算符重载为类的友元函数运算符重载的为类的成员函数,在类中声明的格式为:函数类型operator运算符(参数表);定义该函数的格式:函数类型类名:operator运算符(参数表)函数体;也可以将重载运算符函数的定义直接写在类中。,第8章多态性,8.1运算符重载,8.1.2运算符重载的格式与规则(续)2.运算符重载的规则(1)除“.”、“*”、“:”、“?:”和“sizeof”等几个运算符不能重载外,C+中几乎所有的运算符都可以重载。(2)运算符被重载后,其优先级和结合性不会改变。(3)不能改变运算符操作对象的个数。,第8章多态性,8.2运算符重载为类的成员函数,8.2.1双目运算符重载双目运算符,如果重载为类的成员函数,其参数为一个,即比运算对象少一个。例8.2复数的乘法运算,在上例的基础上添加乘法运算符重载函数。复数类乘法运算的定义如下:(a+bi)*(x+yi)=a*x-b*y+(a*y+b*x)i,第8章多态性,例8.2复数乘法运算源程序,#includeiostream.hclassCComplexprivate:doublereal;doubleimag;public:CComplex(doubler=0,doublei=0);voidPrint();CComplexoperator+(CComplexc);CComplexoperator-(CComplexc);CComplexoperator*(CComplexc);CComplex:CComplex(doubler,doublei)real=r;imag=i;,第8章多态性,例8.2(续一),voidCComplex:Print()cout(real,imag)endl;CComplexCComplex:operator+(CComplexc)CComplextemp;temp.real=real+c.real;temp.imag=imag+c.imag;returntemp;CComplexCComplex:operator-(CComplexc)CComplextemp;temp.real=real-c.real;temp.imag=imag-c.imag;returntemp;,第8章多态性,例8.2(续二),CComplexCComplex:operator*(CComplexc)CComplextemp;temp.real=real*c.real-imag*c.imag;temp.imag=real*c.imag+imag*c.real;returntemp;voidmain(void)CComplexa(1,2),b(3.0,4.0),c,d,e,f;c=a+b;d=a-b;e=a*b;f=a+1;coutc=;c.Print();coutd=;d.Print();coute=;e.Print();coutf=;f.Print();,第8章多态性,程序运行结果为:c=(4,6)d=(-2,-2)e=(-5,10)f=(2,2),总结:设有双目运算符B,如果要重载B为类的成员函数,使之能够实现表达式oprd1Boprd2,其中oprd1为A类对象,则B应被重载为A类的成员函数,形参类型应该是oprd2所属的类型。经重载后,表达式oprd1Boprd2相当于oprd1.operatorB(oprd2),注意重载双目运算符只需要一个参数。,8.2运算符重载为类的成员函数,8.2.2单目运算符重载单目运算符,如果重载为类的成员函数,不需要参数。为区分前置和后置运算符,C+规定:对于前置单目运算符,重载函数没有参数对于后置单目运算符,重载函数有一个整型参数,这个整型参数没有其他用途,只是用于区分前置运算与后置运算。,第8章多态性,例8.3定义一个CInt类,类中只有一个数据成员i,两个运算符“+”的重载函数,一个没有参数,实现的是前置运算符重载,另一个有一个整型参数,实现后置运算符重载。,#includeiostream.hclassCIntprivate:inti;public:CInt(inta=0);voidPrint();CIntoperator+();CIntoperator+(int);CInt:CInt(inta)i=a;,第8章多态性,voidCInt:Print()couti=iendl;CIntCInt:operator+()CInttemp;temp.i=+i;returntemp;CIntCInt:operator+(int)CInttemp;temp.i=i+;returntemp;,例8.3(续),voidmain(void)CInta(5),b(5),c,d;c=a+;d=+b;couta:;a.Print();coutb:;b.Print();coutc:;c.Print();coutd:;d.Print();,第8章多态性,程序运行结果为:a:i=6b:i=6c:i=5d:i=6,8.2运算符重载为类的成员函数,8.2.3赋值运算符重载如果类中只包含简单数据类型的数据成员,则使用C+提供的赋值运算符“=”就可以实现将一个对象赋给另一个对象。如前面复数类的对象,就可以将一个对象直接赋给另一个对象。但如果类的数据成员比较复杂(如含有指针),这样直接赋值就会产生问题,我们必须重载赋值运算符“=”才能正确使用“=”。,第8章多态性,例8.4类A只有一个数据成员str,是一个字符指针,在构造函数中为str申请存储空间并赋值,在析构函数中释放内存。,#includeiostream.h#includestring.hclassAprivate:char*str;public:A(char*s=nodata);A();voidprint();A:A(char*s)intlen=strlen(s);str=newcharlen+1;strcpy(str,s);,第8章多态性,例8.4(续),A:A()if(str)deletestr;voidA:print()coutstrendl;voidmain(void)A*p=newA(AAAA);Aa1;a1=*p;a1.print();deletep;a1.print();,第8章多态性,例8.5带有重载赋值运算符的A类,#includeiostream.h#includestring.hclassAprivate:char*str;public:A(char*s=nodata);A();A,第8章多态性,例8.5(续一),A:A()if(str)deletestr;A,第8章多态性,例8.5(续二),voidmain(void)A*p=newA(AAAA);Aa1;a1=*p;a1.print();deletep;a1.print();,第8章多态性,程序运行结果为:AAAAAAAA,8.3运算符重载为类的友元函数,8.3.1问题的提出(1)复数与复数相加(c1,c2,c3是复数类的对象)。c3=c1+c2;(2)一个复数与一个实数的加法运算c3=c1+10.8;(3)一个实数与一个复数相加就会出现错误。c3=10.8+c1;因为加号左边的运算对象是实数,C+试图将加号右边的运算对象解释为实数,但C+无法将一个复数转换为一个实数,从而产生错误。将运算符重载为友元函数可以解决这个问题。,第8章多态性,8.3运算符重载为类的友元函数,8.3.2运算符重载为友元函数类中的声明:friend函数类型operator运算符(参数表);运算符重载函数的定义形式:函数类型operator运算符(参数表)函数体;,第8章多态性,例8.6用友元函数实现复数类加减运算符的重载,#includeiostream.hclassCComplexprivate:doublereal;doubleimag;public:CComplex(doubler=0,doublei=0);voidPrint();friendCComplexoperator+(CComplexc1,CComplexc2);friendCComplexoperator-(CComplexc1,CComplexc2);CComplex:CComplex(doubler,doublei)real=r;imag=i;,第8章多态性,例8.6(续一),voidCComplex:Print()cout(real,imag)endl;CComplexoperator+(CComplexc1,CComplexc2)CComplextemp;temp.real=c1.real+c2.real;temp.imag=c1.imag+c2.imag;returntemp;CComplexoperator-(CComplexc1,CComplexc2)CComplextemp;temp.real=c1.real-c2.real;temp.imag=c1.imag-c2.imag;returntemp;,第8章多态性,例8.6(续二),voidmain(void)CComplexa(1,2),b(3.0,4.0),c,d,e;c=a+b;d=b-10;e=20+a;coutc=;c.Print();coutd=;d.Print();cout”和插入运算符“中有两个参数,一个是istream流的引用,另一个是用户自定义类complex的引用。,istream,运行结果:输入复数c:输入实部:5输入虚部:-6C=(5-6*i),练习,1.设计日期类Date,包括年、月、日,重载运算符“”、“”,实现Date类对象的输入和输出。,8.4虚函数,8.4.1用虚函数实现动态多态回顾例7.6voidmain()CShape*ps3;CShapes(Red);CPointp1(10,10),p2(100,100),p3(50,50);CLinel(p1,p2,Green);CCirclec(p3,20,Black);ps0=,第8章多态性,程序运行结果为:DrawaShape.ThecolorisRedDrawaShape.ThecolorisGreenDrawaShape.ThecolorisRedBlack,为了能通过基类的指针调用派生类的成员函数,可以使用虚函数的方法,即把成员函数Draw()声明为虚函数。,例8.7用虚函数实现动态多态,#include#includeclassCPointprivate:intX;intY;public:CPoint(intx=0,inty=0)X=x;Y=y;CPoint(CPoint,第8章多态性,例8.7(续一),classCShapeprivate:charColor10;public:CShape(char*c)strcpy(Color,c);virtualvoidDraw()coutDrawaShape.ThecolorisColorendl;voidPrintColor()coutColorendl;,第8章多态性,例8.7(续二),classCLine:publicCShapeprivate:CPointStart;CPointEnd;public:CLine(CPoints,CPointe,char*c):CShape(c),Start(s),End(e)virtualvoidDraw()coutDrawaLinefrom(Start.GetX(),Start.GetY();cout)to(End.GetX(),End.GetY(),withcolor;PrintColor();,第8章多态性,例8.7(续三),classCCircle:publicCShapeprivate:CPointCenter;intRadius;public:CCircle(CPointctr,intr,char*c):CShape(c),Center(ctr)Radius=r;virtualvoidDraw()coutDrawaCircleatcenter(Center.GetX(),;coutCenter.GetY()withradiusRadiusandcolor;PrintColor();,第8章多态性,例8.7(续四),voidmain()CShape*ps3;CShapes(Red);CPointp1(10,10),p2(100,100),p3(50,50);CLinel(p1,p2,Green);CCirclec(p3,20,Black);ps0=,第8章多态性,程序运行结果为:DrawaShape.ThecolorisRedDrawaLinefrom(10,10)to(100,100),withcolorGreenDrawaCircleatcenter(50,50)withradius20andcolorBlack,8.4虚函数,8.4.1用虚函数实现动态多态(续)总结:(1)将成员函数声明为虚函数,在函数原型前加关键字virtual,如果成员函数的定义直接写在类中,也在前面加关键字virtual。(2)将成员函数声明为虚函数后,再将基类指针指向派生类对象,在程序运行时,就会根据指针指向的具体对象来调用各自的虚函数,称之为动态多态。(3)如果基类的成员函数是虚函数,在其派生类中,原型相同的函数自动成为虚函数。,第8章多态性,8.4虚函数,8.4.2用虚函数实现动态多态的机制为了实现动态多态,编译器对每个包含虚函数的类创建一个虚函数地址表,并设置一个虚函数地址指针指向这个对象的虚函数地址表。使用基类指针对虚函数调用时,通过这个虚函数地址指针,在虚函数地址表中查找函数地址。由于包含虚函数的类,有一个虚函数地址指针,与没有虚函数的类相比,含有虚函数类的对象所占用的存储空间要多一个指针所占用的内存。,第8章多态性,例8.8含有虚函数类的对象所占用的存储空间。,#includeclassAprivate:inta;public:virtualvoidfunc();classB:publicAprivate:intb;public:virtualvoidfunc()virtualvoidfunc1();voidmain(void)coutsizeof(A)=sizeof(A)endl;coutsizeof(B)=sizeof(B)endl;,第8章多态性,程序运行结果为:sizeof(A)=8sizeof(B)=12,8.4虚函数,8.4.2用虚函数实现动态多态的机制(续)每个含有虚函数类的对象都有一个虚函数地址指针,指向该类虚函数表,如果用基类的指针调用虚函数,在编译时,并不能确定这个指针的具体指向,而是在运行时,根据指针所指向的具体对象(基类的对象或其派生类的对象),虚函数地址指针才有一个确定的值,即相应类的这个虚函数的地址。从而实现动态多态。,第8章多态性,8.4虚函数,8.4.3虚析构函数析构函数也可以定义为虚函数,如果基类的析构函数定义为虚析构函数,则派生类的析构函数就会自动成为虚析构函数。如果基类的指针指向派生类对象,当用delete删除这个对象时,若析构函数不是虚函数,就要调用基类的析构函数,而不会调用派生类的析构函数。如果为基类和派生类的对象分配了动态内存,或者为派生类的对象成员分配了动态内存,这时释放的只是基类中动态分配的内存,而派生类中动态分配的内存未被释放,因此一般应将析构函数定义为虚析构函数。,第8章多态性,例8.9定义职员类CEmployee,数据成员有姓名(字符指针型数据)和年龄,由CEmployee类派生出教师类CTeacher,增加数据成员教学简历(字符指针型数据)。,#include#includeclassCEmployeeprivate:char*name;intage;public:CEmployee(char*n,inta);virtualCEmployee();CEmployee:CEmployee(char*n,inta)name=newcharstrlen(n)+1;strcpy(name,n);age=a;,第8章多态性,例8.9(续一),CEmployee:CEmployee()coutDestructCEmployeeendl;if(name)deletename;classCTeacher:publicCEmployeeprivate:char*mainCourse;public:CTeacher(char*n,char*course,inta);virtualCTeacher();/由于基类已定义虚析构函数,此处也可不加virtual;CTeacher:CTeacher(char*n,char*course,inta):CEmployee(n,a)mainCourse=newcharstrlen(course)+1;strcpy(mainCourse,course);,第8章多态性,例8.9(续二),CTeacher:CTeacher()coutDestructCTeacherendl;if(mainCourse)deletemainCourse;voidmain(void)CEmployee*p3;p0=newCEmployee(Name1,20);p1=newCTeacher(Name2,Cf
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 建材行业2025年工业机器人自动化生产线应用研究报告
- 人工智能+公共治理智慧城市建设与运营模式研究报告
- 云会计助力中小企业财务报表编制与披露的合规性研究报告
- 课件模板步骤图
- 海洋遥感培训课件
- 陪护员培训课件
- 热力站培训课件
- 神奇的空气课件
- 课件栏目设置
- 志愿服务培训内容
- 传感器技术与应用电子教案
- DB11-T 2021-2022 12345市民服务热线服务与管理规范
- 数学思想方法及其教学课件学习教案
- 人教版(2024)小学信息科技 三年级 第3课《体验人机交互》教学设计
- 《材料力学性能》课程教学大纲
- 《机械常识》(第二版) 课件 第一章 常用金属材料
- 四宫格数独课件
- 保育员取餐分餐环节培训
- 个人简历模板(空白简历表格)
- 保密室搬迁方案设计
- T-HNCAA 023-2020 混凝土砖单位产品综合能耗限额和计算方法
评论
0/150
提交评论