不是所有的運算符都能重載, 以下的都不行 作用域運算符號 成員訪問運算符 成員指針解引用 求類型或者對象大小的運算符 三目運算符 類型信息運算符 寫重載時註意: 不要發明運算符重載,只能對已經有的運算符重載,不能發明運算符 不能對基本類型的運算符的進行重載= 運算符重載中至少有一個類型是類類型 不能 ...
不是所有的運算符都能重載, 以下的都不行
::
作用域運算符號
.
成員訪問運算符
.*
成員指針解引用
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
}