运算符重载
不是所有的运算符都能重载, 以下的都不行 ::
作用域运算符号 .
成员访问运算符 .*
成员指针解引用 sizeof
求类型或者对象大小的运算符 ?:
三目运算符 typei
类型信息运算符 写重载时注意:
- 不要发明运算符重载,只能对已经有的运算符重载,不能发明运算符
- 不能对基本类型的运算符的进行重载=>运算符重载中至少有一个类型是类类型
- 不能改变运算符的运算特性和优先级,比如把二元运算符改成一元的
- 只能重载成成员的运算符:=,+= ,-=, *=, /=, %=,[] 下标取值,() 圆括号运算符,-> 指针运算符,* 指针解引用运算符
- 只能重载成全局函数的运算符:>>, <<
- 如果不给一个类型提供赋值运算符,则编译器会体统一个默认的赋值运算符,这个运算符完成的是逐字节拷贝,这样会产生多个指针指向同一块内存,并且可能产生内存泄露。类似缺省的拷贝构造
+,*,*=重载
clasFraction{ inx; iny; public: Fraction(inx=int y=1):x(x),y(y){} voishow(){ cout<<x<<'/'<<y<<endl; } //成员形式的运算符重载,this充当第一个参数,且可以省略 Fractiooperator+(const Fraction& fb)const{ //有这个的话不能和全局的区分,只留一个就行, returFraction(x*fb.y+y*fb.x,y*fb.y); } Fractiooperator*(const Fraction& fb)const{ returFraction(x*fb.x,y*fb.y); } Fractiooperator*=(const Fraction& fb){ //当前对象要变,不能加const x*=fb.x; y*=fb.y; retur*this; } }; //全局形式 Fractiooperator+(const Fraction& fa,const Fraction& fb){ returFraction(fa.x*fb.y+fa.y*fb.x,fa.y*fb.y); } clasInteger{ indata; public: Integer(indata=:data(data){ //后半部分才是真正的构造 } voishow(){ cout<<data<<endl; } /* //使用成员函数实现operator+ Integeoperator+(const Integer& i)const{ // returInteger(data+i.data); //匿名对象 returdata+i.data; //单参构造 } */ stativoid showData(Integer* mythis){ //static函数使用普通变量要this cout<<mythis->data<<endl; } private: //声明友元 frienconst Integer operator+(const Integer& ia,const Integer& ib); }; //使用全局函数实现operator+ consInteger operator+(const Integer& ia,const Integer& ib){ //正常情况下权限有问题,可以定义一个getData()函数或用友元解决 //开头的const是为了保证返回的临时结果不可以被覆盖 returInteger(ia.data+ib.data); }
cout/cin重载
cout是ostream& 流类型不能复制,必须用引用类型,也不能const修饰,cin同理,编译器会先去ostream类型(L对象)中找一个成员函数operator<<(const Integer&)
,如果找不到就去全局找一个全局函数operator<<(ostream& ps,const Interger& i)
#include<iostream> usinnamespace std; clasInteger{ indata; public: Integer(indata=:data(data){ //后半部分的初始化列表的部分才是真正的构造 } frienostream& operator<<(ostream& os,const Integer& i); frienistream& operator>>(istream& is,Integer& i); //成员形式的operator== boooperator==(const Integer& i){ returdata==i.data; //返回指针的话this==&i(极少用) } }; //全局形式的输出运算符重载 ostreamoperator<<(ostream& os,const Integer& i){ returos<<i.data; } //全局形式的输入运算符重载 istreamoperator>>(istream& is,Integer& i){ returis>>i.data; } inmain(){ Integeia(,ib(0); if(ia==ib){ cin>>ia; cout<<ia<<endl; } retur }
二元运算符L#R的重载中编译器会先去L对象对应的类型中找一个重载函数叫operator#(R),没有就去全局函数中找一个全局函数叫operator#(L,R),最后综合选择最优调用
一元运算符重载
先去O对象对应的类型找一个成员函数叫operator#()
, 如果找不到就去全局找一个全局函数operator#(O)
,#默认操作符号在前,操作数在后
clasInteger{ indata; public: Integer(indata=:data(data){ //后半部分才是真正的构造 } frienostream& operator<<(ostream& os,const Integer& i); frienistream& operator>>(istream& is,Integer& i); boooperator!(){ retur!data; } Integeoperator-(){ retur-data; } Integeroperator--(){ //前-- data--; retur*this; } consInteger operator--(int){ //后-- /* Integetmp=*this; data--; returtmp; */ returdata--; //返回的是变化之前的结果 } Integeroperator++(){ //前++ data++; retur*this; } consInteger operator++(int){ //后++ returdata++; } }; //全局形式的输出运算符重载 ostreamoperator<<(ostream& os,const Integer& i){ returos<<i.data; } //全局形式的输入运算符重载 istreamoperator>>(istream& is,Integer& i){ returis>>i.data; } inmain(){ Integeia(,ib(); cout<<!ia<<endl; cout<<!ib<<endl; cout<<-ia<<endl; cout<<-ia<<endl; //注意是两个-,不是-- cout<<-(-ia)<<endl; cout<<--ia<<endl; cout<<ia--<<endl; cout<<ia<<endl; cout<<++ia<<endl; cout<<ia++<<endl; cout<<ia<<endl; cout<<-ib<<endl; }
new/delete运算符重载
clasA{ inx; iny; public: A(){cout<<"A()"<<endl;} ~A(){cout<<"~A()"<<endl;} }; stativoid* operator new(size_t size){ //new运算符全局的成员的都一个样 cout<<"size="<<size<<endl; returmalloc(size); } stativoid operator delete(void* ptr){ cout<<"ptr="<<ptr<<endl; } inmain(){ Apa=new A(); deletpa; retur } strin对象的使用: inmain(){ strinstra("hello"); strinstrb="hello"; strb="world"; if(stra==strb) cout<<"stra==strb"<<endl; else cout<<"stra!=strb"<<endl; cout<<strb<<endl; cout<<(strb.append(test"))<<endl; cout<<(stra+=test")<<endl; cout<<(stra=stra+strb)<<endl; cout<<stra.size()<<endl; cout<<stra[4]<<endl; cout<<stra.at(4)<<endl; //把C++ string 变成const char* const char* mystr=stra.c_str(); cout<<mystr<<endl; cout<<strlen(mystr)<<endl; }
()的重载
#include<iostream> using namespace std; class Product{ //产品数量 int pcount; //产品单价 double price; public: Product(int pcount=0,double price=0.0):pcount(pcount),price(price){} //重载()运算符 double operator()(int c,double p){ return c*p; } double operator()(int c,double p,double pct){ return c*p*pct; } //重载()运算符,把当前对象类型变成int //int operator() (){ //Wrong! operator int(){ // return pcount; } //把当前对象类型转换成double operator double(){ return price; } }; int main(){ Product iphone; double sumprice=iphone(9,.6); //对象已经创建了,这里的()可不是初始化 cout<<sumprice<<endl; cout<<iphone(9,.6,0.8)<<endl; Product iphone6s(99,.4); int c=(int)iphone6s; cout<<c<<endl; double p=(double)iphone6s; cout<<p<<endl; return 0; }
例子
#include<iostream> using namespace std; class Array{ //数组容量 int len; //元素的个数 int size; //真正存储数据的指针 int* data; public: //构造 expliciArray(int len=:len(len),size(0){ //size一定要初始化为否则容易越界 //申请堆内存 data=neint[len]; } //析构 ~Array(){ //释放堆内存 delete[data; } //拷贝构造 Array(consArray& arr){ //浅拷贝 len=arr.len; size=arr.size; //深拷贝,重新申请堆内存 data=neint[len]; //复制数据 for(ini=i<size;i++) data[i]=arr.data[i]; } //添加数据 voipush_back(int d){ if(size>=len) expand(); data[size++]=d; } //扩容 voiexpand(){ len=len+1; //记录原来的内存 in*tmp=data; //重新申请堆内存 data=neint[len]; //复制数据 for(ini=i<size;i++) data[i]=tmp[i]; //释放原来的内存 delete[tmp; } //显示数据 //其实是全局函数写在了类内,输入输出重载不能在类内 friend ostream& operator<<(ostream& os,const Array& arr){ cout<<'['; for(ini=i<arr.size;i++) cout<<arr.data[i]<<' '; cout<<"]"; } //赋值运算符重载 Arrayoperator=(const Array& arr){ //防止自赋值 if(this!=&arr){ len=arr.len; size=arr.size; //释放原来的内存,防止原来的空间不够大 delete[data; //重新申请内存 data=neint[len]; //复制数据 for(ini=i<size;i++){ data[i]=arr.data[i]; } } retur*this; } //[]运算符的重载 intoperator[](const unsigned int i){//operator[]不能有默认值,因为有了默认值作为二元运算符的[]就变成了单目运算符 retur*(data+i); } }; voifoo(){ Arraarra(; arra.push_back(; arra.push_back(; arra.push_back(; arra.push_back(; arra.push_back(; Arraarrb; arrb=arra; cout<<arrb[<<endl; cout<<arrb<<endl; } inmain(){ foo(); retur }
相关推荐
wbczyh 2019-11-02
mieleizhi0 2019-11-07
ppppl 2010-03-17
choupiaoyi 2017-10-11
ephesians 2016-08-24
peterlee 2017-05-04
JnX 2010-03-26
wztwzt 2019-04-07
文山羊 2015-08-19
Winterto0 2017-08-27
HeyShHeyou 2019-04-26
小金屋 2015-06-01
uglygirl 2015-05-28
chenmingwei 2009-09-04
dgdafas 2009-08-31
ARTELE 2009-08-12
fundebug 2019-03-29