面向对象程序设计语言C++第05章_运算符重载.ppt
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 面向 对象 程序设计语言 C++ 05 运算 重载
- 资源描述:
-
第一章 引论,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,面向对象程序设计语言,C+,电子科技大学计算机学院,1,第五章 运算符重载,当在使用一种程序设计语言编写程序时,我们不仅要设计新的数据类型,同时还要为新类型设计,运算,。一般地,用户定义类型的运算都是用函数的方式实现的。,而在一般情况下,一种类型的运算都是用,运算符,表达的,这很直观,语义也简单。,但是如果直接将运算符作用在用户定义类型之上,那么编译器将不能识别运算符的语义。因此,在这种情况下,我们需要一种特别的机制来重新定义作用在用户定义类型上的普通运算符的含义。这就是,运算符重载,的简单概念,。,2,第五章 运算符重载,其实在,C,编译器里早就存在简单的运算符重载的概念了。考虑整型和浮点型两种加法运算:,int,a=1,b;b=a+2,;,float c=1.0,d;,d=c+2.0;,在上面的两条加法语句中,都用到了运算符,“,+,”,。这符合我们数学常识。但对于,C,编译器来说,这两个加法却被翻译成不同的指令。这就是说,,“,+,”,运算符至少具有两种不同的解释(实现代码)。此时我们说,,“,+,”,运算符被重载了。遗憾的是,,C,仅支持很少量的运算符重载。,3,第五章运算符重载,C+,扩充了,C,运算符重载的功能,允许已存在的预定义运算符在不同的上下文中做出不同的解释。,当两个字符串类进行连接的时候,我们可能用到这样的方式:,class String,public:,String,string_cat(String,);,;,String str1,str2,str3;,str3=str1.string_cat(str2);,4,第五章运算符重载,显然,这不如,str3=str1+str2,简单明了。,但问题是,,C+,编译器只知道,+,运算符是作用在整型和浮点型数据之上的,它不知道在上述表达式中,+,运算符的确切含义。,因此,在设计类,String,时,我们必须,增加,“,+”,运算符的含义。这样一来,语义变得更加清晰和易懂。,5,第五章 引论,在原来预定义的运算符含义的基础上,再增加对于某个用户定义类型的对象进行操作的新的含义。这就是,运算符重载,。,运算符重载后,其优先级和结合性,不变,。,6,第五章 引论,考虑复数的加法运算:,class Complex,double re,im,;,public:,Complex(double,r,double,im,),re=r;,im,=i;,Complex()re=0.0;,im,=0.0;,Complex,add_Complex(Complex,c),Complex temp;,temp.re,=re+,c.re,;,temp.im,=,im,+,c.im,;,return temp;,;,7,/,整个函数体也可简化为,return,Complex(re+c.re,im+c.im,);,第五章 引论,void main(),Complex obj1(1,2),obj2(3,4);,Complex obj3=,obj1.add_Complex(obj2),;,能不能将,2,个复数相加表示为:,obj1+obj2,呢?,9,第五章 引论,5.1,重载运算符,C+,提供了一种将标准定义的运算符用在用户自定义类型上的方法,称为,运算符重载,。,C+,约定,如果一个成员函数的函数名字是特殊的,即由关键字,operator,加上一个运算符构成,如,operator+,。,obj1.operator+(obj2),称为函数,operator+(),的,显示调用形式,;,obj1+obj2,称为函数,operator+(),的,隐式调用形式,;,函数,operator+(),称为,运算符重载函数,。,10,第五章 引论,考虑复数的加法运算:,class Complex,double re,im,;,public:,Complex(double,r,double,im,),re=r;,im,=i;,Complex()re=0.0;,im,=0.0;,Complex,operator+,(Complex,c,),Complex temp;,temp.re,=re+,c.re,;,temp.im,=,im,+,c.im,;,return temp;,;,11,第五章 引论,5.1,重载运算符,void main(),Complex obj1(1,2),obj2(3,4);,Complex obj3=,obj1.+obj2,;,obj1+obj2,等价于:,obj1.operator+(obj2),12,第五章 引论,5.1.1,运算符重载的语法形式,在,C+,中,运算符通过一个运算符重载函数进行重载。运算符重载可以采用,成员函数,和友元函数两种重载方式,语法形式如下:,(1),运算符重载函数为,成员函数,的语法形式为:,type,Class_Name:operator,(,参数表,),/,相对于,Class_Name,类而定义的操作,其中,,type,是返回类型,,“,”,是要重载的运算符符号,,Class_Name,是重载该运算符的类的类名,函数名,operator,。,13,第五章 引论,5.1.1,运算符重载的语法形式,(2),运算符重载函数为,友元函数,的语法形式为:,type operator(,参数表,),/,相对于该类而定义的操作,14,第五章 引论,5.1.2,重载运算符规则,(1),只有少数的,C+,语言的运算符不能重载:,:#?:.*,15,第五章 引论,5.1.2,重载运算符规则,(2),只能对,已有,的,C+,运算符进行重载。,(3),重载运算符时,,不能,改变它们的,优先级,,,不能,改变它们的,结合性,,也,不能,改变这些运算符所需,操作数的数目,。,(4),重载运算符的函数,不能有默认的参数,,否则就改变了运算符所需要的操作数的数目。,16,第五章 引论,5.1.2,重载运算符规则,(5),重载的运算符必须和用户自定义类型的对象一起使用,其参数至少应用一个是类对象(或类对象的引用)。,(6),用于类对象的运算符一般必须重载,有两个运算符:赋值运算符,=,和地址运算符,&,可以不必重载,17,第五章 引论,5.1.2,重载运算符规则,(7),重载运算符时,可以让运算符执行,任意,的操作,,比如将,运算符重载为运算,但这样违背了运算符重载的初衷,降低程序可读性,使人无法理解程序功能。,因此,应当使重载运算符的功能类似于该运算符作用于标准类型数据时所实现的功能。,如果不能建立运算符的这种习惯用法,应该采用函数调用方法,以免造成阅读困难(,除非程序员故意如此,)。,18,第五章 引论,5.1,重载运算符,5.1.3,一元和二元运算符,1.,一元运算符,一元运算符,不论是前缀还是后缀,都需要一个操作数。,暂时不区分前缀和后缀的重载,(,5.1.5,节:前缀和后缀重载的区别)。,19,第五章 引论,5.1.3,一元和二元运算符,对任意一元运算符,,有:,(1),成员函数,重载运算符,type,Class_Name:operator,(),设,obj,为,Class_Name,的类对象,则:,显式调用方式:,obj.operator,(),隐式调用方式:,obj,或者,obj,20,成员函数,Complex,Complex:operator,!(),Complex temp;,temp.re,=-re;,temp.im,=-,im,;,return temp;,第五章 引论,5.1.3,一元和二元运算符,(2),友元函数重载运算符,type,operator(Class_Name,Cobj,),显式调用方式:,operator(obj,),隐式调用方式:,obj,或者,obj,(例,5-5/6,),22,友元函数,Complex,operator!(const,Complex&,obj,),Complex temp;,temp.re,=-,obj.re,;,temp.im,=-,obj.im,;,return temp;,第五章 引论,5.1.3,一元和二元运算符,2.,二元运算符,(1),成员函数重载运算符,type,Class_Name:operator(Class_Name,Cobj,),显式调用方式:,obj1.operator(obj2),隐式调用方式:,obj1 obj2,24,第五章 引论,5.1.3,一元和二元运算符,(2),友元函数重载运算符,type operator(,Class_Name,Cobj1,Class_Name Cobj2),显式调用方式:,operator(obj1,obj2),隐式调用方式:,obj1 obj2,(例,5-7/8,),25,成员函数,Complex,Complex,:operator+(,const Complex&,obj,),Complex temp;,temp.re,=,re+obj.re,;,temp.im,=,im+obj.im,;,return temp;,友元函数,Complex,operator+(const,Complex&,aobj,const Complex&,bobj,),Complex temp;,temp.re,=,aobj.re+bobj.re,;,temp.im,=,aobj.im+bobj.im,;,return temp;,第五章 引论,5.1.3,一元和二元运算符,3,运算符重载为成员函数和友元函数的选择建议,28,non-member,All other binary operators,member,+=/=*=&=|=%=*,member,All unary operators,Recommended Use,Operator,第五章 引论,5.1,重载运算符,5.1.4,重载,+,和,-,的前缀和后缀方式,以,+,为例:,对于前缀方式,+,obj,:,成员函数重载,Class_Name,Class_Nam:operator,+();,友元函数重载,Class_Nam,operator+(Class_Nam,&,);,29,成员函数,Complex&,Complex:operator,+(),/,前缀,re+;,im,+;,return*this;,Complex,Complex:operator+(int,)/,后缀,Complex c(*this);/,拷贝构造函数,re+;,im,+;,return c;,第五章 引论,5.1,重载运算符,5.1.4,重载,+,和,-,的前缀和后缀方式,对于后缀方式,obj,+:,成员函数重载,Class_Nam,Class_Nam:operator+(,int,);,友元函数重载,Class_Nam,operator+(Class_Nam,&,int,);,这时,第二个参数,(,int,),只是一个,占位,符号,用来区分该重载函数是前缀方式还是后缀方式,在函数内部不需要也不能使用。通常用,0,表示。,(例,5-11/12,),31,有元函数,Complex&,operator+(Complex,&,obj,),obj.re,+;,obj.im,+;,return,obj,;,Complex,operator+(Complex,&,obj,int,),Complex,c(obj,);/,拷贝构造函数,obj.re,+;,obj.im,+;,return c;,第五章 引论,5.1,重载运算符,5.1.5,重载赋值运算符,赋值运算符,“,=”,可以被重载,用户可以定义自己需要的重载“,=,”的运算符重载函数。重载了的运算符函数,operator=,不能被继承,,而且它必须被重载为,成员函数,,一般重载格式为:,X,X:operator,=(const X&from),/,复制,X,的成员,拷贝构造函数和赋值运算符都是把一个对象的数据成员拷贝到另一对象。它们的区别是,拷贝构造函数要,创建,一个新对象,而赋值运算符则是,改变,一个已存在的对象的值。,(例,5-13,),33,第五章 引论,5.1.6,重载运算符,(),和,运算符,“,()”,和运算符,“,”,不能用友元函数重载,只能采用,成员函数,重载。,1,重载函数调用运算符,(),对应的运算符重载函数为,operator()(),设,obj,为类,Class_Nam,的一个对象,则表达式,obj(arg1,arg2),可被解释为,obj.operator()(arg1,arg2),(例,5-14,),34,第五章 引论,5.1.6,重载运算符,(),和,2,重载下标运算符,相应的运算符重载函数为,operator(),设,xobj,为类,X,的对象,则表达式,xobjarg,解释为,xobj.operator,(,arg,),(例,5-15,),需要注意,这里的参数,arg,必须是一个整型表达式。,35,考虑一个整数数组,数组的大小在定义时初始化;,可以将对象,(,名,),直接作为数组,(,名,),;,使用而且其大小在运行时可以改变。,class,Arrayint,*,p;int,size;,public:,Array(int,num),size=(num6)?num:6;,p=new,intsize,;,Array(),delete p;,int,&,operator(int,idx,),if(,idx,size)return,pidx,;,else expend(idx-size+1);,return,pidx,;,void,expend(int,off),int,*pi;,pi=new,int,size+off;,for(,int,n=0;nsize;n+),pin=pn;,delete p;,p=pi;,size+=off;,void,contract(int,offset),size=size-offset;,;/,类结束,void main(),int,num=0;,Array a_Array(10);,for(;num 10;num+),a_Arraynum=num;,a_Array,10,=10;,for(n=0;n=10;n+),cout,”,和,“,”,进行输入和输出。,42,输出运算符“,”,的第一个操作数是,cout,,它实际上是标准类类型,ostream,的对象的引用,(,它的定义在文件,iostream,中,),。,若在程序中,用户自己定义 一个,ostream,的对象的引用,则也可以直接使用运算符“,”,。,#include,void main(),int,num=10;,ostream,&scout=,cout,;,scoutnum”,的第一个操作数是,cin,,它实际上是标准类类型,istream,的对象的引用,(,它的定义在文件,iostream,中,),。,若在程序中,用户自己定义 一个,istream,的对象的引用,也可以直接使用运算符“,”,。,第五章 引论,5.1.7,重载输入和输出运算符,对于类类型,用户可以重载运算符,“,”,和,“,”,以满足自己的需要。,对某个用户定义的类类型,Class_Name,重载输出运算符,“,”,,重载函数的函数名为,operator,。,只能使用,友元,函数进行重载,;,为了保证输出运算符“,也有类似的情况,但要注意第二个参数必须是对象的引用。,(例,5-16,),45,class Complex,double,re,im,;public:,friend,ostream,&operator(,istream,;,ostream,&,operator(,ostream,&,os,Complex&c),os,0),os,+,c.im,i,endl,;,else,os,c.im,i(,istream,&,is,Complex,&,c),is,c.re,c.im,;,return is;,void main(),Complex obj1,obj2;,cout,obj1obj2;,cout,obj1“”size;,cp=new,Complexsize,;,49,第五章 引论,5.2.3,指针悬挂问题,指针悬挂就是指:使用,new,申请的存储空间无法访问,也无法释放。,造成指针悬挂原因是对指向,new,申请的存储空间的指针变量进行赋值修改。,char*p,*q;,p=new char10;q=new char10;,strcpy(p,abcd,);,q=p;,delete p;delete q;,/,错误,同样的空间被释放两次,50,对象的拷贝有两种方式:,初始化和赋值,。,将一个对象的数据成员对应地赋值给另一个对象的数据成员;,如果一个类包含有指针类型的数据成员,那么,该类的对象的,拷贝,(,初始化和赋值,),就,可能会有问题,。,对象的指针成员直接赋值,就可能导致指针悬挂。,需要,重新定义拷贝构造函数和超载,“,=”,的函数,class String,char*,pstr;int,sz,;,public:,String(,int,s),pstr,=new char,sz,=s;,String(),delete ,pstr,;,;,void main(),String str1(10);,String str2=str1;,String str3(10);,str3=str1;,执行该程序,会出现问题。,Why?,缺省的拷贝构造函数为:,String:String(const String&,str,),pstr,=,str.pstr,;,sz,=,str.sz,;,修改为,String:String(const,String&,str,),pstr,=new,charsz,=,str.sz,;,strcpy(pstr,str.pstr,);,缺省的超载”,=”,函数为:,String String:operator=(const String&,str,),pstr,=,str.pstr,;,sz,=,str.sz,;,修改为,String,String,:operator=(const String&,str,),char*pstr1=new,charsz,=,str.sz,;,strcpy(pstr1,str.pstr);,delete,pstr,;,pstr,=pstr1;,return*this;,集合的实现,C+,中没有集合类型,可以定义一个集合类来实现。,与集合相关的操作有:,加入,一个元素到集合中,判断,一个元素是否在集合中,可以取两个集合的,交集,和,并集,删除,集合中的一个元素,可以,扩充,集合,可以,输入、输出,集合的所有元素,集合可以互相,复制,可以,清空,一个集合,等,class Set,int,*p;,int,size;,int,have,;,public:,Set(int,a);,Set();,void,expend,(int,offset);,void,add,(int,);,int,In,(int,);,void,delete_item,(int,);,Set,operator+(,Set);,Set,operator*(,Set t);,friend void operator(,ostream,Set(const Set,Set operator=(const Set,void clear();,;,Set Set:operator*(Set t),Set temp(size);,for(,int,a=0;a-1),temp.add(pa);,return temp;,Set Set:operator+(Set t),Set temp(size+t.size);,int,a;,for(a=0;ahave;a+),temp.add(pa,);,for(a=0;a,t.have;a,+),if(,In(t.pa,)=-1),temp.add(t.pa,);,return temp;,Set:Set(const Set&t),p=new,intsize,=t.size;,have=t.have;,for(int,num=0;numhave;num+),pnum=,t.pnum,;,Set Set:operator=(const Set&t),if(this!=&t),delete p;,p=new,intsize,=t.size;,have=,t.have,;,for(int,n=0;n,标准类型,标准类型,-,类类型,类类型,-,标准类型,类类型,-,类类型,65,第五章 引论,5.3,类型转换运算符的重载,5.3.1,标准类型转换为类类型,可以通过自定义的,重载赋值号,“,=”,的函数和,构造函数,实现标准类型,-,类类型;它们都需要有标准类型的参数。,具有标准类型参数的构造函数说明了一种从参数类型到该类类型的转换。,(例,5-24/25,),66,class INTEGER,int,num;,public:,INTEGER(,int,i);,INTEGER(const char*,str,);,INTEGER:INTEGER(int,i),num=i;,INTEGER:INTEGER(const,char*,str,),num=,strlen(str,);,void main(),INTEGER obj1=1,;,INTEGER obj2=Cheng;,obj1=20;/obj1.operator=(INTEGER(20);,obj2=,Du,;/*obj2.mem_fun(INTEGER(3);*/,第五章 引论,5.3,类型转换运算符的重载,5.3.2,类类型转换函数,带一个参数的构造函数可以进行类型转换,但是它的转换功能很受限制。,引入一种特殊的成员函数:,类型转换函数,,它在类对象之间提供一种类似显式类型转换的机制。,68,第五章 引论,5.3,类型转换运算符的重载,5.3.2,类类型转换函数,C+,允许程序员为类定义一个类型转换函数,它的语法是,Class_Name:operator,type(),return(type,类型的实例,);,类型转换函数,没有参数,,,没有返回类型,,但这个函数体内必须有一条,返回语句,,返回一个,type,类型的实例。,69,第五章 引论,5.3,类型转换运算符的重载,5.3.2,类类型转换函数,class INTEGER ,int,num;,public:,INTEGER(int,anint,=0)num=,anint,;,operator,int,(),return num;,;,70,void main(),INTEGER obj(12);,int,anint,=,int(obj,),;,anint,=,(,int)obj,;,anint,=,obj,;,/,obj.operator,int,(),实现一个,Point,类(数据成员为一个点在两维直角坐标系内的坐标);,实现一个,Vector,类(数据成员为一个点在两维极坐标系内的坐标);,要求两个类的对象能互相赋值。,#include,#include,const double PI=3.14;,class Vector;,class Point,friend Vector;,int,x;,int,y;,public:,Point(int,initx,=0,int,inity,=0),x=,initx;y,=,inity,;,operator Vector();,friend,ostream,&operator,(,ostream,&s,Point,obj,),s,obj.x,obj.y,n;,return s;,;,class Vector,friend Point;,double p;double seta;,public:,Vector(double,initp,=0,double,initseta,=0),p=,initp;seta,=,initseta,;,operator Point();,friend,ostream,&operator,(,ostream,&s,Vector,obj,),s,obj.p,obj.seta,0),Vobj.seta,=PI/2;,else,if (y0),Vobj.seta,=3*PI/2;,else,Vobj.seta,=0;,else,Vobj.seta,=,atan(y/x,);,return,Vobj,;,展开阅读全文
咨信网温馨提示:1、咨信平台为文档C2C交易模式,即用户上传的文档直接被用户下载,收益归上传人(含作者)所有;本站仅是提供信息存储空间和展示预览,仅对用户上传内容的表现方式做保护处理,对上载内容不做任何修改或编辑。所展示的作品文档包括内容和图片全部来源于网络用户和作者上传投稿,我们不确定上传用户享有完全著作权,根据《信息网络传播权保护条例》,如果侵犯了您的版权、权益或隐私,请联系我们,核实后会尽快下架及时删除,并可随时和客服了解处理情况,尊重保护知识产权我们共同努力。
2、文档的总页数、文档格式和文档大小以系统显示为准(内容中显示的页数不一定正确),网站客服只以系统显示的页数、文件格式、文档大小作为仲裁依据,个别因单元格分列造成显示页码不一将协商解决,平台无法对文档的真实性、完整性、权威性、准确性、专业性及其观点立场做任何保证或承诺,下载前须认真查看,确认无误后再购买,务必慎重购买;若有违法违纪将进行移交司法处理,若涉侵权平台将进行基本处罚并下架。
3、本站所有内容均由用户上传,付费前请自行鉴别,如您付费,意味着您已接受本站规则且自行承担风险,本站不进行额外附加服务,虚拟产品一经售出概不退款(未进行购买下载可退充值款),文档一经付费(服务费)、不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
4、如你看到网页展示的文档有www.zixin.com.cn水印,是因预览和防盗链等技术需要对页面进行转换压缩成图而已,我们并不对上传的文档进行任何编辑或修改,文档下载后都不会有水印标识(原文档上传前个别存留的除外),下载后原文更清晰;试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓;PPT和DOC文档可被视为“模板”,允许上传人保留章节、目录结构的情况下删减部份的内容;PDF文档不管是原文档转换或图片扫描而得,本站不作要求视为允许,下载前可先查看【教您几个在下载文档中可以更好的避免被坑】。
5、本文档所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用;网站提供的党政主题相关内容(国旗、国徽、党徽--等)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
6、文档遇到问题,请及时联系平台进行协调解决,联系【微信客服】、【QQ客服】,若有其他问题请点击或扫码反馈【服务填表】;文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“【版权申诉】”,意见反馈和侵权处理邮箱:1219186828@qq.com;也可以拔打客服电话:0574-28810668;投诉电话:18658249818。




面向对象程序设计语言C++第05章_运算符重载.ppt



实名认证













自信AI助手
















微信客服
客服QQ
发送邮件
意见反馈



链接地址:https://www.zixin.com.cn/doc/13187563.html