版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第13章运算符重载13.1实现基础
13.2双目运算符重载13.3关系运算符重载13.4单目运算符重载13.5赋值运算符重载13.6new与delete运算符重载11113.7特殊运算符重载13.8类型转换运算符13.9输入输出运算符重载13.10本章小结13.1实现基础22对运算符重载主要有两种方式实现:(1)利用成员函数形式实现运算符重载。(2)利用友元函数形式实现运算符重载。33例13.1:成员函数实现向量加法运算符重载。#include<iostream>usingnamespacestd;
classVector{private:
intx;
inty;public:
Vector(intx=0,inty=0){
this->x=x;
this->y=y;
}
Vectoradd(Vector&v){
Vectorrv;
rv.x=x+v.x;
rv.y=y+v.y;
returnrv;}Vectoroperator+(Vector&v){Vectorrv;rv.x=x+v.x;rv.y=y+v.y;
returnrv;
}
voidshow()
{
cout<<'('<<x<<','<<y<<')'<<endl;
}};intmain(){
Vectorv1(1,2),v2(3,4),v3,v4;
v3=v1.add(v2);
v4=v1+v2;
v3.show();
v4.show();
return0;}44例13.2:友元函数实现向量加法运算符重载。#include<iostream>usingnamespacestd;classVector{private:
intx;
inty;public:
Vector(intx=0,inty=0){
this->x=x;
this->y=y;}
voidshow(){
cout<<'('<<x<<','<<y<<')'<<endl;}
//友元形式,加法运算符重载函数实现向量加法
friendVectoroperator+(Vector&v1,Vector&v2);};Vectoroperator+(Vector&v1,Vector&v2){
Vectorrv;
rv.x=v1.x+v2.x;
rv.y=v1.y+v2.y;
returnrv;}intmain(){
Vectorv1(1,2),v2(3,4),v3;
v3=v1+v2;
v3.show();
return0;}5513.2双目运算符重载对于算术双目运算符,包括算术运算符(+,-,*,/,%)的重载均可以参考前一节中的示例来实现。对于其他双目运算符,比如逻辑运算中的(&&,||)或者位运算中的(&,|)等均可以采取类似的思路来实现。66例13.3:不同类型参数的算术运算符+重载示例。#include<iostream>usingnamespacestd;classVector{private:
intx;
inty;public:
Vector(intx=0,inty=0){
this->x=x;
this->y=y;
}
voidshow()
{
cout<<'('<<x<<','<<y<<')'<<endl;}
//当前对象与一个整数的算术加法运算
Vectoroperator+(intn){
Vectorrv;
rv.x=x+n;
rv.y=y;
returnrv;}
friendVectoroperator+(intn,Vector&v);};Vectoroperator+(intn,Vector&v){
Vectorrv;
rv.x=v.x;
rv.y=v.y+n;
returnrv;}
intmain(){
Vectorv1(1,2),v2;
v2=v1+10;
v2.show();
v2=100+v1;
v2.show();
return0;}77
13.3关系运算符重载C++支持各种关系运算符,包括<、>、<=、>=、==、!=等等,它们可用于比较C++内置的数据类型。可以用成员函数或友元函数重载这些关系运算符,重载后的关系运算符可用于比较类的对象。88
例13.4:向量关系运算符(<)示例#include<iostream>usingnamespacestd;classVector{private:
intx;
inty;public:
Vector(intx=0,inty=0)
{
this->x=x;
this->y=y;
}
//对象比较
booloperator<(Vector&v)
{
if(x<v.x&&y<v.y)
{
returntrue;}
returnfalse;
}};intmain(){
Vectorv1(1,2),v2(3,4);
if(v1<v2)
{
cout<<"v1islessthanv2"<<endl;
}
else
{
cout<<"v1isnotlessthanv2"<<endl;
}
return0;}9913.4单目运算符重载单目运算符包括自增(++),自减(--),负号(-),逻辑非(!)运算符几种,其中自增和自减运算符还包括运算符的前置和后置两种情况。前置自增(++),前置自减(--),负号(-),以及逻辑非(!)的运算符重载类似,而后置自增(++)以及后置自减(--)情况稍有不同。1010例13.5:单目运算符重载示例。Vector(intx=0,inty=0){this->x=x;this->y=y;}voidshow(){cout<<"("<<x<<","<<y<<")"<<endl;}//前置++运算Vector&operator++(){x++;y++;return*this;}//后置++运算Vectoroperator++(int){Vectorv(*this);x++;y++;returnv;}//前置-运算Vector&operator-(){x=-x;y=-y;return(*this);}//前置!运算
Vector&operator!(){x=-x;return(*this);}Vectorv1(1,2),v2;cout<<"v1=";v1.show();cout<<"v2=++v1"<<endl;v2=++v1;//调用前置++运算cout<<"v1=";v1.show();cout<<"v2=";v2.show();cout<<"v2=v1++"<<endl;v2=v1++;//调用后置++运算cout<<"v1=";v1.show();cout<<"v2=";v2.show();cout<<"v2=-v1"<<endl;v2=-v1;//调用前置-运算
cout<<"v1=";v1.show();cout<<"v2=";v2.show();cout<<"v2=!v1"<<endl;v2=!v1;//调用前置!运算cout<<"v1=";v1.show();cout<<"v2=";v2.show();111113.5赋值运算符重载类在建立后,会有默认的赋值运算函数,也就是进行同类对象之间的赋值,但这种赋值只是对应数据成员之间的浅拷贝,对于涉及到指针指向的更多被分配的内存(使用new运算符分配的堆区内存),并不能自动进行动态分配内存后拷贝,这个问题和默认的拷贝构造函数类似。赋值运算符=可以被重载,可以拓展对象被赋值的范围,或者修改默认赋值运算中的浅拷贝带来的问题,比如内存重复释放(见10.5)。12例13.6
赋值运算符重载示例。classmyString{private:intlen;char*pstr;voidcopyString(constchar*srcString){pstr=newchar[len];char*mypc=pstr;for(inti=0;srcString[i]!='\0';i++,mypc++){*mypc=srcString[i];}*mypc='\0';}public:myString(){len=0;pstr=NULL;}voidshowString(){cout<<pstr<<endl;}voidoperator=(constchar*srcString){cout<<"overloadedfunction(1)"<<endl;len=0;for(inti=0;srcString[i]!='\0';i++,len++);copyString(srcString);}voidoperator=(constmyString&obj){cout<<"overloadedfunction(2)"<<endl;len=obj.len;copyString(obj.pstr);}~myString(){delete[]pstr;}};intmain(){myStringobj1,obj2;obj1="IloveC++";//调用重载函数(1)obj1.showString();obj2=obj1;//调用重载函数(2)obj2.showString();return0;}1313.6new与delete运算符重载在C++中动态内存申请使用new运算符,动态内存释放使用delete运算符。在使用new运算符时,系统首先需要分配合适的内存,然后调用类的构造函数。使用delete运算符时,系统首先调用类的析构函数,然后释放对象所占用的内存。14【例13.7】new和delete运算符重载。//全局new函数重载void*operatornew(size_tlen){
cout<<"globalnew"<<endl;
void*ptr=malloc(len);
returnptr;}//全局delete函数重载voidoperatordelete(void*ptr){
cout<<"globaldelete"<<endl;
if(ptr!=NULL){
free(ptr);
}}classmyString{public:
intlen;
myString(intl)
{
len=l;}//类内new函数重载void*operatornew(size_tl){cout<<"classnew"<<endl;
void*ptr=malloc(l);
returnptr;
}
//类内delete函数重载
voidoperatordelete(void*ptr)
{
cout<<"classdelete"<<endl;
if(ptr!=NULL){
free(ptr);
}}
voidshow()
{
cout<<"myStringlen:"<<len<<endl;}
~myString(){
cout<<"Destruction"<<endl;
}};intmain(){
//调用全局new和delete函数
int*pi=newint(100);
cout<<"int:"<<*pi<<endl;
deletepi;
//调用类内new和delete函数
myString*pobj=newmyString(200);
pobj->show();
deletepobj;1513.7特殊运算符重载C++中还存在一些可以进行运算符重载的特殊运算符,比如(),->,逗号,[]等。16
13.7.1()函数调用运算符函数调用运算符()可以被重载成可以调用多种参数的函数调用。这种形式可以把对象当作函数的形式来使用,有时也称为函数对象或仿函数。例13.8()函数调用重载示例。17classScreen{private:intx;inty;public:Screen(intx,inty){this->x=x;this->y=y;}//无参的()重载函数voidoperator()(){cout<<"x="<<x<<",y="<<y<<endl;}//有参的()重载函数voidoperator()(intz){cout<<"x="<<x+z/2<<",y="<<y+z/2<<endl;}};intmain(){Screenobj(1080,900);obj();//调用无参的()重载函数obj(1000);//调用有参的()重载函数return0;}1813.7.2->成员访问运算符成员访问运算符->可以作为类的成员函数被重载,重载后,类在形式上具有了指针的功能,该函数内部需要返回一个指针。例13.9
->成员访问运算符重载示例。19structPixel{intx;inty;};classScreen{private:Pixel*origin;public:Screen(intx,inty){origin=newPixel;origin->x=x;origin->y=y;}//->运算符重载Pixel*operator->(){returnorigin;}
~Screen(){deleteorigin;cout<<"Destruction"<<endl;}};intmain(){Screenobj(1000,2000);cout<<"x="<<obj->x<<",y="<<obj->y<<endl;return0;}2013.7.3[]下标访问运算符下标访问运算符[]的重载可以访问类内数组中的元素,使用该运算符重载可以克服C++中一般数组下标访问可能会越界的问题,通过对该运算符的重载,可以为自定义的数据提供安全的数组访问。例13.10
下标访问运算符重载示例。C++程序设计及项目实践2121classmyString{private:intlen;char*pstr;public:myString(constchar*str){for(len=0;str[len]!='\0';len++);pstr=newchar[len];for(inti=0;i<len;i++){pstr[i]=str[i];}pstr[len]='\0';}//下标访问运算符[]的重载charoperator[](intindex){if(index>len||index<0){returnpstr[0];}returnpstr[index];}voidshow(){cout<<pstr<<endl;}
~myString(){
if(len)
{
delete[]pstr;}
}};intmain(){
myStringobj("IloveC++");
obj.show();
cout<<obj[100]<<'\t'<<obj[3]<<'\t'<<obj[100]<<endl;
return0;}C++程序设计及项目实践222213.8类型转换运算符用户自定义类的有时需要向其他类型转换,或者将其他类型转换为用户自定义的类,这就需要使用两种方法,一种是其他类型向当前类转换的转换构造函数,另一种是当前类向其他类型转换的类型转换运算符重载。C++程序设计及项目实践2313.8.1转换构造函数:其他类型向类转换通过转换构造函数,可以将基础数据类型或其他类类型转换为当前类类型,从而实现其他类型向当前类的转换,这种功能的实现依赖于只有一个参数的构造函数。
例13.11
转换构造函数示例。C++程序设计及项目实践24classVector{private:
intx;
inty;public:
Vector(){
x=y=-1;
}
//显式转换
explicitVector(inti)
{
x=i;
y=0;
}
//隐式转换
Vector(charc)
{
x=y=c;
}
voidshow()
{
cout<<"("<<x<<","<<y<<")"<<endl;
}};intmain(){
Vectorv;
v.show();
v=static_cast<Vector>(3);//必须显式转换
v.show();
v='z';//支持隐式转换
v.show();
return0;}C++程序设计及项目实践2513.8.2类型转换运算符:类向其他类型转换类型转换函数可以将当前类转换为其他类类型,一般是转换为基础数据类型,此时可以定义一个类型重载函数,语法形式如下: operator类型名()const { 转换功能; return类型值; } 该函数无需返回值类型定义,直接返回对应类型的值即可。例13.12
类型转换运算符重载示例。C++程序设计及项目实践26classVector{private:intx;inty;public:Vector(){x=y=-1;}//将当前类类型转换为int类型operatorint()const{returnx;}};intmain(){Vectorv;inti=3+v;cout<<i<<endl;return0;}C++程序设计及项目实践2713.9输入输出运算符重载>>运算符的重载形式为: istream&operator>>(istream&is,类名&对象名) { 实现输入功能; returnis; } <<运算符的重载形式为: ostream&operator<<(ostream&os,类名&对象名) { 实现输出功能; returnos; }
例13.13
输入输入运算符重载示例。C++程序设计及项目实践28classmyString{private:intlen;char*pstr;public:myString(){len=0;pstr=NULL;
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- SSGF新建造体系全穿插施工工艺施工方案
- Unit 7 课时4 Section A Grammar Focus(大单元课时课件)英语新教材人教版八年级下册
- it业务外包合同
- 三星镇市容外包合同
- 业务员外包合同
- 中型软件外包合同
- 临时工劳务外包合同
- 交通运输外包合同
- 仓储公司外包合同
- 企业用人外包合同
- 2026新教材语文 22《〈礼记〉二则-大道之行也》教学课件
- 浙江省Z20联盟2026届高三年级第三次学情诊断日语+答案
- 2026湖北供销集团有限公司招聘66人考试模拟试题及答案解析
- 2025年书记员速录技能考试真题及答案
- 2026年卫生统计学模拟试题+参考答案
- (2026年)共青团入团考试试题(含答案)
- 2026年夏令营行业分析报告及未来发展趋势报告
- 总包对分包的管理排查清单
- 2026年湖南娄底市中考生物试题及答案
- 2025厌氧好氧缺氧(AOA)活性污泥法设计标准
- 中国酱油行业发展现状调查、竞争格局分析及未来前景预测报告
评论
0/150
提交评论