面向对象程序设计语言C第章运算符重载

上传人:无*** 文档编号:169701041 上传时间:2022-11-16 格式:PPT 页数:79 大小:1.01MB
收藏 版权申诉 举报 下载
面向对象程序设计语言C第章运算符重载_第1页
第1页 / 共79页
面向对象程序设计语言C第章运算符重载_第2页
第2页 / 共79页
面向对象程序设计语言C第章运算符重载_第3页
第3页 / 共79页
资源描述:

《面向对象程序设计语言C第章运算符重载》由会员分享,可在线阅读,更多相关《面向对象程序设计语言C第章运算符重载(79页珍藏版)》请在装配图网上搜索。

1、面向对象程序设计语言C+电子科技大学计算机学院1第五章 运算符重载 当在使用一种程序设计语言编写程序时,我们不仅要设计新的数据类型,同时还要为新类型设计运算。一般地,用户定义类型的运算都是用函数的方式实现的。而在一般情况下,一种类型的运算都是用运算符表达的,这很直观,语义也简单。但是如果直接将运算符作用在用户定义类型之上,那么编译器将不能识别运算符的语义。因此,在这种情况下,我们需要一种特别的机制来重新定义作用在用户定义类型上的普通运算符的含义。这就是运算符重载的简单概念。2第五章 运算符重载 其实在C编译器里早就存在简单的运算符重载的概念了。考虑整型和浮点型两种加法运算:int a=1,b;

2、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;

3、str3=str1.string_cat(str2);4第五章运算符重载 显然,这不如 str3=str1+str2 简单明了。但问题是,C+编译器只知道+运算符是作用在整型和浮点型数据之上的,它不知道在上述表达式中+运算符的确切含义。因此,在设计类String时,我们必须增加“+”运算符的含义。这样一来,语义变得更加清晰和易懂。5第五章 引论 在原来预定义的运算符含义的基础上,再增加对于某个用户定义类型的对象进行操作的新的含义。这就是运算符重载。运算符重载后,其优先级和结合性不变。6第五章 引论考虑复数的加法运算:class Complex double re,im;public:Compl

4、ex(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、引论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;Comple

6、x()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+中,运算符通过一个运算符重载函数进行重载。运算符重载可以采用成员函数和友元函数两种重载方式,语法

7、形式如下:(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 重载运算符规

8、则重载运算符规则(2)只能对已有的C+运算符进行重载。(3)重载运算符时,不能改变它们的优先级,不能改变它们的结合性,也不能改变这些运算符所需操作数的数目。(4)重载运算符的函数不能有默认的参数,否则就改变了运算符所需要的操作数的数目。16第五章 引论5.1.2 重载运算符规则重载运算符规则(5)重载的运算符必须和用户自定义类型的对象一起使用,其参数至少应用一个是类对象(或类对象的引用)。(6)用于类对象的运算符一般必须重载,有两个运算符:赋值运算符=和地址运算符&可以不必重载17第五章 引论5.1.2 重载运算符规则重载运算符规则(7)重载运算符时,可以让运算符执行任意的操作,比如将运算符重

9、载为运算 但这样违背了运算符重载的初衷,降低程序可读性,使人无法理解程序功能。因此,应当使重载运算符的功能类似于该运算符作用于标准类型数据时所实现的功能。如果不能建立运算符的这种习惯用法,应该采用函数调用方法,以免造成阅读困难(除非程序员故意如此)。18第五章 引论5.1 重载运算符5.1.3 一元和二元运算符一元和二元运算符1.一元运算符一元运算符 一元运算符,不论是前缀还是后缀,都需要一个操作数。暂时不区分前缀和后缀的重载,(5.1.5节:前缀和后缀重载的区别)。19第五章 引论5.1.3 一元和二元运算符一元和二元运算符对任意一元运算符,有:(1)成员函数重载运算符type Class_

10、Name:operator()设obj为Class_Name的类对象,则:显式调用方式:obj.operator()隐式调用方式:obj 或者 obj20成员函数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!(cons

11、t 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 obj224第五章 引论5.1.3一元和二元运算符一元和二元运算符(2)友元函数重载运算符 type operator(Class_Name Cobj1,Class_Name Cobj2)显式调用

12、方式: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.

13、3一元和二元运算符一元和二元运算符3运算符重载为成员函数和友元函数的选择建议运算符重载为成员函数和友元函数的选择建议28第五章 引论 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

14、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.i

15、m+;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的成员 拷贝构造函数和赋值运算符都是把一个对象的数据成员拷贝到另一对象。它们的区别是,拷贝构造函数要创建一

16、个新对象,而赋值运算符则是改变一个已存在的对象的值。(例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的对象,则表达式xobja

17、rg解释为xobj.operator(arg)(例5-15)需要注意,这里的参数arg必须是一个整型表达式。35 考虑一个整数数组考虑一个整数数组 数组的大小在定义时初始化;数组的大小在定义时初始化;可以将对象可以将对象(名名)直接作为数组直接作为数组(名名);使用而且其大小在运行时可以改变。使用而且其大小在运行时可以改变。class class ArrayintArrayint *p;intp;int size;size;public:public:Array(intArray(int num)num)size=(num6)?num:6;size=(num6)?num:6;p=new p=n

18、ew intsizeintsize;Array()Array()delete p;delete p;intint&operator(intoperator(int idxidx)if(if(idxidxsize)return size)return pidxpidx;else expend(idx-size+1);else expend(idx-size+1);return return pidxpidx;void void expend(intexpend(int off)off)intint *pi;pi;pi=new pi=new intint size+off;size+off;for

19、(for(intint n=0;nsize;n+)n=0;nsize;n+)pin=pn;pin=pn;delete p;delete p;p=pi;p=pi;size+=off;size+=off;void void contract(intcontract(int offset)offset)size=size-offset;size=size-offset;/;/类结束类结束void main()void main()intint num=0;num=0;Array a_Array(10);Array a_Array(10);for(;num 10;num+)for(;num 10;nu

20、m+)a_Arraynum=num;a_Arraynum=num;a_Arraya_Array1010=10;=10;for(n=0;n=10;n+)for(n=0;n=10;n+)coutcouta_Arrayn;”和“”进行输入和输出。42 输出运算符“”的第一个操作数是cout,它实际上是标准类类型ostream的对象的引用(它的定义在文件iostream中)。若在程序中,用户自己定义 一个ostream的对象的引用,则也可以直接使用运算符“”。#include void main()int num=10;ostream&scout=cout;scoutnum”的第一个操作数是cin,它

21、实际上是标准类类型istream的对象的引用(它的定义在文件iostream中)。若在程序中,用户自己定义 一个istream的对象的引用,也可以直接使用运算符“”。第五章 引论5.1.7重载输入和输出运算符重载输入和输出运算符 对于类类型,用户可以重载运算符“”和“”以满足自己的需要。对某个用户定义的类类型Class_Name重载输出运算符“”,重载函数的函数名为operator。只能使用友元函数进行重载;为了保证输出运算符“也有类似的情况,但要注意第二个参数必须是对象的引用。(例5-16)45class Complex double re,im;public:friend ostream&

22、operator(istream&,Complex&);ostream&operator(ostream&os,Complex&c)os0)os+c.imiendl;else osc.imi(istream&is,Complex&c)isc.rec.im;return is;void main()Complex obj1,obj2;coutobj1obj2;coutobj1“”size;cp=new Complexsize;49第五章 引论5.2.3 指针悬挂问题指针悬挂问题指针悬挂就是指:使用new申请的存储空间无法访问,也无法释放。造成指针悬挂原因是对指向new申请的存储空间的指针变量进行

23、赋值修改。char*p,*q;p=new char10;q=new char10;strcpy(p,abcd);q=p;delete p;delete q;/错误,同样的空间被释放两次50 对象的拷贝有两种方式:对象的拷贝有两种方式:初始化和赋值初始化和赋值。将一个对象的数据成员对应地赋值给另一个对象的将一个对象的数据成员对应地赋值给另一个对象的数据成员;数据成员;如果一个类包含有指针类型的数据成员,那么,该如果一个类包含有指针类型的数据成员,那么,该类的对象的类的对象的拷贝拷贝(初始化和赋值初始化和赋值)就就可能会有问题可能会有问题。对象的指针成员直接赋值,就可能导致指针悬挂。对象的指针成员

24、直接赋值,就可能导致指针悬挂。需要需要重新定义拷贝构造函数和超载重新定义拷贝构造函数和超载“=”的函数的函数class String class String char char*pstr;intpstr;int szsz;public:public:String(String(intint s)s)pstrpstr=new char=new char szsz=s;=s;String()String()delete delete pstrpstr;void main()void main()String str1(10);String str1(10);String str2=str1;St

25、ring str2=str1;String str3(10);String str3(10);str3=str1;str3=str1;执行该程序,会出现问题。执行该程序,会出现问题。Why?Why?缺省的拷贝构造函数为:String:String(const String&String:String(const String&strstr)pstrpstr=str.pstrstr.pstr;szsz=str.szstr.sz;修改为修改为String:String(constString:String(const String&String&strstr)pstrpstr=new=new ch

26、arszcharsz=str.szstr.sz;strcpy(pstr,str.pstrstrcpy(pstr,str.pstr););缺省的超载缺省的超载”=”=”函数为:函数为:String String:operator=(const String&String String:operator=(const String&strstr)pstrpstr=str.pstrstr.pstr;szsz=str.szstr.sz;修改为修改为String String StringString:operator=(const String&:operator=(const String&strs

27、tr)char char*pstr1=new pstr1=new charszcharsz=str.szstr.sz;strcpy(pstr1,str.pstr);strcpy(pstr1,str.pstr);delete delete pstrpstr;pstrpstr=pstr1;=pstr1;return return*this;this;集合的实现集合的实现 C+C+中没有集合类型,可以定义一个集合类来实现。中没有集合类型,可以定义一个集合类来实现。与集合相关的操作有:与集合相关的操作有:加入加入一个元素到集合中一个元素到集合中 判断判断一个元素是否在集合中一个元素是否在集合中 可以取

28、两个集合的可以取两个集合的交集交集和和并集并集 删除删除集合中的一个元素集合中的一个元素 可以可以扩充扩充集合集合 可以可以输入、输出输入、输出集合的所有元素集合的所有元素 集合可以互相集合可以互相复制复制 可以可以清空清空一个集合一个集合等等class Set class Set intint *p;p;intint size;size;intint have have;public:public:Set(intSet(int a);a);Set();Set();void void expendexpend(int(int offset);offset);void void addadd(i

29、nt(int););intint InIn(int(int););void void delete_itemdelete_item(int(int););Set Set operator+(operator+(Set);Set);Set Set operator operator*(Set t);Set t);friend void operator(friend void operator(ostreamostream&,Set);&,Set);Set(const Set&);Set(const Set&);Set operator=(const Set&);Set operator=(co

30、nst Set&);void clear();void clear();Set Set:operatorSet Set:operator*(Set t)(Set t)Set temp(size);Set temp(size);for(for(intint a=0;ahave;a+)a=0;a-1)if(t.In(pa)-1)temp.add(pa);temp.add(pa);return temp;return temp;Set Set:operator+(Set t)Set Set:operator+(Set t)Set temp(size+t.size);Set temp(size+t.s

31、ize);intint a;a;for(a=0;ahave;a+)for(a=0;ahave;a+)temp.add(patemp.add(pa););for(a=0;a for(a=0;at.have;at.have;a+)+)if(if(In(t.paIn(t.pa)=-1)=-1)temp.add(t.patemp.add(t.pa););return temp;return temp;Set:Set(const Set&t)Set:Set(const Set&t)p=new p=new intsizeintsize=t.size;=t.size;have=t.have;have=t.h

32、ave;for(intfor(int num=0;numhave;num+)num=0;numhave;num+)pnum=pnum=t.pnumt.pnum;Set Set:operator=(const Set&t)Set Set:operator=(const Set&t)if(this!=&t)if(this!=&t)delete p;delete p;p=new p=new intsizeintsize=t.size;=t.size;have=have=t.havet.have;for(intfor(int n=0;n n=0;n标准类型 标准类型-类类型 类类型-标准类型 类类型-

33、类类型65第五章 引论 5.3 类型转换运算符的重载5.3.1 标准类型转换为类类型标准类型转换为类类型可以通过自定义的重载赋值号“=”的函数和构造函数实现标准类型-类类型;它们都需要有标准类型的参数。具有标准类型参数的构造函数说明了一种从参数类型到该类类型的转换。(例5-24/25)66class 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()I

34、NTEGER 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:

35、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;70void main()INTEGER obj(12);int anint=int(obj);anint=(int)obj;anint=obj;/obj.operator int(

36、)实现一个实现一个PointPoint类(数据成员为一个点在两维直角坐类(数据成员为一个点在两维直角坐标系内的坐标);标系内的坐标);实现一个实现一个VectorVector类(数据成员为一个点在两维极坐类(数据成员为一个点在两维极坐标系内的坐标);标系内的坐标);要求两个类的对象能互相赋值。要求两个类的对象能互相赋值。#include#include const double PI=3.14;class Vector;class Point class Point friend Vector;friend Vector;intint x;x;intint y;y;public:public:

37、Point(intPoint(int initxinitx=0,int=0,int inityinity=0)=0)x=x=initx;yinitx;y=inityinity;operator Vector();operator Vector();friend friend ostreamostream&operator&operator (ostreamostream&s,Point&s,Point objobj)s sobj.xobj.x,obj.yobj.yn;n;return s;return s;class Vectorclass Vector friend Point;friend

38、 Point;double p;double seta;double p;double seta;public:public:Vector(double Vector(double initpinitp=0,double=0,double initsetainitseta=0)=0)p=p=initp;setainitp;seta=initsetainitseta;operator Point();operator Point();friend friend ostreamostream&operator&operator (ostreamostream&s,Vector&s,Vector objobj)ssobj.pobj.p,obj.setaobj.setan;0)if (y0)Vobj.setaVobj.seta=PI/2;=PI/2;elseelseif (y0)if (y0)Vobj.setaVobj.seta=3=3*PI/2;PI/2;else else Vobj.setaVobj.seta=0;=0;else else Vobj.setaVobj.seta=atan(y/xatan(y/x););return return VobjVobj;

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

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

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


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