版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第9章运算符重载运算符重载与函数重载相似,其目的是设置某一运算符,让它具有另一种功能,尽管此运算符在原先C++语言中代表另一种含义,但它们彼此之间并不冲突。
C++会根据运算符的位置辨别应使用哪一种功能进行运算。9.1运算符重载概述运算符重载是对已有的运算符赋予多重含义,同一个运算符作用于不同类型的数据导致不同类型的行为。
C++中预定义的运算符的操作对象只能是基本数据类型,实际上,对于很多用户自定义类型(比如类),也需要有类似的运算操作,这就提出了对运算符进行重新定义,赋予已有符号以新功能的要求。!~+-*&/%<<>><<=>>===!=^|&&>+=-=*=/=%=&=^=|=<<=>>=,->*->()[]=++--newdeleteC++中可以重载的运算符C++中不可以重载的运算符
..*::?:运算符重载的规则如下:(1)C++中的运算符除了少数几个之外,全部可以重载,而且只能重载已有的这些运算符。(2)重载之后运算符的优先级和结合性都不会改变。(3)运算符重载是针对新类型数据的实际需要,对原有运算符进行适当的改造。一般来讲,重载的功能应当与原有功能相类似,不能改变原运算符的操作对象个数,同时至少要有一个操作对象是自定义类型。运算符的重载形式有两种:重载为类的成员函数和重载为类的友元函数。运算符重载为类的函数的语法格式如下:
•
格式1:使运算符函数作为类的成员函数函数类型operator运算符(形参表){
函数体;}
•
格式2:使运算符函数作为类的friend函数
friend函数类型operator运算符(形参表){
函数体;}一般来讲,单目运算符最好重载为成员函数,而双目运算符则最好重载为友元函数。运算符重载的主要优点就是允许改变使用于系统内部的运算符的操作方式,以适应用户新定义类型的类似运算。9.2重载单目运算符在C++中,单目运算符有++和--,它们是变量自动增1和自动减1的运算符。在类中可以对这两个单目运算符进行重载。【例】分析以下程序的执行结果。#include<iostream.h>classSample{intn;public:
Sample(inti){n=i;}operator++(){n++;}//“++”运算符重载
voiddisplay(){cout<<"n="<<n<<endl;}};voidmain(){SampleA(5);++A;A.display();}n=6如同“++”运算符有前缀和后缀两种使用形式一样。“++”和“--”重载运算符也有前缀和后缀两种运算符重载形式,以“++”重载运算符为例,其语法格式如下:函数类型operator++(); //前缀运算函数类型operator++(int); //后缀运算使用前缀运算符的语法格式如下:
++对象;使用后缀运算符的语法格式如下:对象++;【例】分析以下程序的执行结果。#include<iostream.h>classSample{intn;public:
Sample(inti){n=i;}operator++(){ n++;} //前缀运算符
operator++(int){n+=2;} //后缀运算符
voiddisplay(){cout<<"n="<<n<<endl;}};voidmain(){SampleA(5),B(5);A++; //调用后缀重载运算符
++B; //调用前缀重载运算符
A.display();B.display();}n=7n=6【例】分析以下程序的执行结果。#include<iostream.h>classSample{intn;public:
Sample(inti){n=i;}
intoperator++() //前缀运算符
{n++;returnn;}
intoperator++(int)//后缀运算符
{n+=2;returnn;}};voidmain(){SampleA(5),B(5);
cout<<"n="<<A++<<endl;
cout<<"n="<<++B<<endl;}n=7n=69.3重载双目运算符运算符重载实质上就是函数重载,如果重载为成员函数,它就可以自由地访问本类的数据成员。实际使用时,总是通过该类的某个对象来访问重载的运算符。对于双目运算符,一个运算数是对象本身的数据,由this指针给出,另一个运算数则需要通过运算符重载函数的参数表来传递。下面分别介绍这两种情况。对于双目运算符B,如果要重载B为类的成员函数,使之能够实现表达式“oprd1Boprd2”,其中oprd1为A类的对象,则应当把B重载为A类的成员函数,该函数只有一个形参,形参的类型是oprd2所属的类型。经过重载之后,表达式oprd1Boprd2就相当于函数调用“oprd1.operatorB(oprd2)”。【例】分析以下程序的执行结果。#include<iostream.h>classVector{intx,y;public:Vector(){};
Vector(intx1,inty1){x=x1;y=y1;}Vectoroperator+(Vectorv)//成员函数方式重载运算符“+”{Vectortmp;//定义一个tmp对象
tmp.x=x+v.x;tmp.y=y+v.y;returntmp;//返回tmp对象
}Vectoroperator-(Vectorv)//成员函数方式重载运算符“-”
{Vectortmp;//定义一个tmp对象
tmp.x=x-v.x;tmp.y=y-v.y;returntmp;//返回tmp对象
}
voiddisplay(){cout<<"("<<x<<","<<y<<")"<<endl;}};voidmain(){Vectorv1(6,8),v2(3,6),v3,v4;
cout<<"v1=";v1.display();
cout<<"v2=";v2.display();v3=v1+v2;
cout<<"v1+v2=";v3.display();v4=v1-v2;
cout<<"v1-v2=";v4.display();}v1=(6,8)v2=(3,6)v1+v2=(9,14)v1-v2=(3,2)运算符也可以重载为类的友元函数,这样,它就可以自由地访问该类的任何数据成员。这时,运算符所需要的运算数都需要通过函数的形参表来传递,在参数表中形参从左到右的顺序就是运算符运算数的顺序。【例】分析以下程序的执行结果。#include<iostream.h>classVector{intx,y;public:Vector(){};
Vector(intx1,inty1){x=x1;y=y1;}friendVectoroperator+(Vectorv1,Vectorv2)//友元函数方式重载运算符“+”{Vectortmp;//定义一个tmp对象
tmp.x=v1.x+v2.x;
tmp.y=v1.y+v2.y;returntmp;//返回tmp对象
}
friendVectoroperator-(Vectorv1,Vectorv2)//友元函数方式重载运算符“-”
{Vectortmp;//定义一个tmp对象
tmp.x=v1.x-v2.x;
tmp.y=v1.y-v2.y;returntmp;//返回tmp对象
}voiddisplay(){cout<<"("<<x<<","<<y<<")"<<endl;}};voidmain(){Vectorv1(6,8),v2(3,6),v3,v4;
cout<<"v1=";v1.display();
cout<<"v2=";v2.display();v3=v1+v2;
cout<<"v1+v2=";v3.display();v4=v1-V2;
cout<<"v1-v2=";v4.display();}v1=(6,8)v2=(3,6)v1+v2=(9,14)v1-v2=(3,2)9.4重载比较运算符除了前面介绍的单目运算符和双目运算符重载外,也可以设计比较运算符(如>、<或==)的重载函数。比较运算符重载函数必须返回真(非0)或假(0)。
【例】编写一个程序,测试输入的长度能否构成一个三角形。解:构成三角形的条件是任意两边之和大于第三边。#include<iostream.h>classLine{int
len;public:
Line(intn){len=n;}Lineoperator+(Linel) //“+”运算符重载
{intx=len+l.len;returnLine(x);}
booloperator>(Linel) //“>”运算符重载
{return(len>l.len)?1:0;}};voidmain(){Linea(10),b(5),c(14);if((a+b>c)&&(a+c>b)&&(b+c>a))
cout<<"能够构成一个三角形"<<endl;else
cout<<"不能够构成一个三角形"<<endl;}能够构成一个三角形9.5重载赋值运算符在C++中有两种类型的赋值运算符:一类是“+=”和“-=”等先计算后赋值的运算符,另一类是“=”即直接赋值的运算符。下面分别进行讨论。9.5.1重载运算符“+=”和“-=”
对于标准数据类型,“+=”和“-=”的作用是将一个数据与另一个数据进行加法或减法运算后再将结果回送给赋值号左边的变量中。对它们重载后,使其实现其他相关的功能。【例】分析以下程序的执行结果。#include<iostream.h>classVector{intx,y;public:Vector(){};
Vector(intx1,inty1){x=x1;y=y1;}friendVectoroperator+=(Vectorv1,Vectorv2) {v1.x+=v2.x;v1.y+=v2.y;returnv1;成员函数方式实现
}Vectoroperator-=(Vectorv) {Vectortmp; //定义一个tmp对象
tmp.x=x-v.x;tmp.y=y-v.y;returntmp; //返回tmp对象
}voiddisplay(){cout<<"("<<x<<","<<y<<")"<<endl;}};友元函数方式实现voidmain(){Vectorv1(6,8),v2(3,6),v3,v4;
cout<<"v1=";v1.display();
cout<<"v2=";v2.display();v3=v1+=v2;
cout<<"v3=v1+=v2后,v3=";v3.display();v4=v1-=v2;
cout<<"v4=v1-v2后,v4=";v4.display();}v1=(6,8)v2=(3,6)v3=v1+=v2后,v3=(9,14)v4=v1-v2后,v4=(3,2)9.5.2重载运算符“=”
赋值运算符“=”的原有含义是将赋值号右边表达式的结果拷贝给赋值号左边的变量。通过运算符“=”的重载将赋值号右边对象的私有数据依次复制到赋值号左边对象的私有数据中。在正常情况下,系统会为每一个类自动生成一个默认的完成上述功能的赋值运算符,当然,这种赋值只限于由同一个类类型说明的对象之间赋值。【例】分析以下程序的执行结果。#include<iostream.h>#include<string.h>classSample{char*p;public:Sample(char*pn){p=newchar[strlen(pn)+1];
strcpy(p,pn);}~Sample(){deletep;} Sample&operator=(Sample&s)//“=”重载成员函数
{deletep;p=newchar[strlen(s.p)+1];
strcpy(p,s.p);return*this;}voiddisp(){cout<<p<<endl;}};voidmain(){Sampleinst1("firstobject");Sampleinst2("secondobject");
cout<<"执行赋值语句之前:"<<endl;
cout<<"inst1*p=";inst1.disp();
cout<<"inst2*p=";inst2.disp();
cout<<"执行赋值语句之后:"<<endl;inst2=inst1;
cout<<"inst1*p=";inst1.disp();
cout<<"inst2*p=";inst2.disp();}执行赋值语句之前:inst1*p=firstobjectinst2*p=secondobject
执行赋值语句之后:inst1*p=firstobjectinst2*p=firstobject9.6重载下标运算符下标运算符“[]”通常用于取数组的某个元素,下标运算符重载可以实现数组下标的越界检测等。下标运算符重载函数只能作为类的成员函数,不能作为类的友元函数。【例】分析以下程序的执行结果。#include<iostream.h>#include<string.h>classwords{int
len;char*str;public:words(char*s){str=newchar[strlen(s)+1];strcpy(str,s);
len=strlen(s);}charoperator[](intn) //下标运算符重载的成员函数
{if(n>len-1) //数组超界判断
{cout<<"数组下标超界";return''; //返回一个特殊字符
}elsereturn*(str+n);}voiddisp(){cout<<str<<endl;}};voidmain(){wordsword("ThisisC++Book");
word.disp();
cout<<"位置0:";
cout<<word[0]<<endl;//显示'T'
cout<<"位置15:";
cout<<word[15]<<endl;//显示'k'
cout<<"位置25:";
cout<<word[25]<<endl;//超界}
ThisisC++Book
位置0:T
位置15:k
位置25:数组下标超界9.7重载运算符new与deleteC++提供了new与delete两个运算符用于内存管理,在大多数情况下,它们是非常有效的。但有些情况下我们需要自已管理内存,以克服new与delete的不足。这就要重载运算符new与delete,使其按照要求完成对内存的管理。【例】分析以下程序的执行结果。#include<iostream.h>#include<malloc.h>classRect{intlength,width;public:
Rect(int
l,intw){length=l;width=w;}voiddisp(){cout<<"面积:"<<length*width<<endl;}void*operatornew(size_tsize)//重载new运算符成员函数
{cout<<"重载new运算符分配内存"<<endl;returnmalloc(size);}voidoperatordelete(void*p)//重载delete运算符成员函数
{free(p);
cout<<"重载delete运算符释放内存"<<endl;}};voidmain(){
Rect*p; //定义对象指针
p=newRect(5,9); //对象指针p指向一个无名对象
p->disp();deletep;}重载new运算符分配内存面积:45重载delete运算符释放内存9.8重载逗号运算符逗号运算符是双目运算符,和其他运算符一样,我们也可以通过重载逗号运算符来完成期望完成的工作。逗号运算符构成的表达式为“左运算数,右运算数”,该表达式返回右运算数的值。如果用类的成员函数来重载逗号运算符,则只带一个右运算数,而左运算数由指针this提供。【例】分析以下程序的执行结果。#include<iostream.h>#include<malloc.h>classPoint{intx,y;public:Point(){};
Point(int
l,intw){x=l;y=w;}voiddisp(){cout<<"面积:"<<x*y<<endl;}Pointoperator,(Pointr)//逗号运算符重载成员函数
{Pointtemp;temp.x=r.x;temp.y=r.y;returntemp;}Pointoperator+(Pointr){Pointtemp;temp.x=r.x+x;temp.y=r.y+y;returntemp;}};voidmain(){Pointr1(3,3),r2(5,8),r3(2,4);r1.disp();r2.disp();r3.disp();r1=(r1,r2+r3,r3);r1.disp();}面积:9面积:40面积:8面积:89.9重载类型转换运算符
C++中提供了标准类型的相互转换,如执行语句:
n=(int)1.87;
则n=1。同样,我们可以进行这种类型转换运算符重载。这种重载运算符函数的格式如下:
operator类型名(){
函数体;
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 《家乐福模式分析》课件
- 管理顾问工作总结
- 房地产行业客服经验分享
- 服装行业的保安工作总结
- 中央财经大学财务管理课件-风险与报酬
- 银行求职自我介绍(15篇)
- 2023-2024年项目部治理人员安全培训考试题(原创题)
- 《电子政务》课件
- 2024年公司项目部负责人安全教育培训试题含答案(模拟题)
- 销售个人年度工作总结(7篇)
- GB/T 32491-2016玻璃纤维增强热固性树脂管及管件长期静水压试验方法
- 书名号测试的文档
- 交大医学院研究生现代免疫学基础和进展《免疫学原理》考试重点
- 全文解读改革开放简史专题解读
- 热电厂工程燃煤系统施工方案
- 福建省南平市各县区乡镇行政村村庄村名明细及行政区划代码
- 金融科技课件(完整版)
- 中国建筑史经典题型
- 计算机信息系统分级保护方案
- 顶管施工技术全面详解
- 公路工程质量检验评定标准(交安部分)
评论
0/150
提交评论