運算符重載的基礎就是運算符重載函數。因此今天主要講的是運算符重載函數。 html
1.運算符重載是對已有的運算符賦予多重含義,使同一個運算符做用域不一樣類型的數據致使不一樣行爲的發生。好比 ios
1 int i; 2 int i1=10,i2=10; 3 i=i1+i2; 4 std::cout<<"i1+i2="<<i<<std::endl; 5 6 double d; 7 double d1=20,d2=20; 8 d=d1+d2; 9 std::cout<<"d1+d2="<<d<<std::endl;
在這個程序裏"+"既完成兩個整形數的加法運算,又完成了雙精度型的加法運算。爲何同一個運算符"+"能夠用於完成不一樣類型的數據的加法運算?這是由於C++針對預約義基本數據類型已經對"+"運算符作了適當的重載。在編譯程序編譯不一樣類型數據的加法表達式時,會自動調用相應類型的加法運算符重載函數。可是C++中所提供的預約義的基本數據類型畢竟是有限的,在解決一些實際的問題時,每每須要用戶自定義數據類型。好比高中數學裏所提到的複數: 函數
1 class Complex //複數類 2 { 3 public: 4 double real;//實數 5 double imag;//虛數 6 Complex(double real=0,double imag=0) 7 { 8 this->real=real; 9 this->imag=imag; 10 } 11 }
假如咱們創建兩個複數,並用"+"運算符讓它們直接相加: 工具
1 Complex com1(10,10),com2(20,20),sum; 2 sum=com1+com2;
那麼會提示沒有與這些操做數匹配的 "+" 運算符的錯誤。這是由於Complex類類型不是預約義類型,系統沒用對該類型的數據進行加法運算符函數的重載。C++就爲運算符重載提供了一種方法,即運算符重載函數。其函數名字規定爲operator後緊跟重載運算符。好比:operator+(),operator*()等。如今咱們給上述程序聲明一個加法運算符的重載函數用於完成複數的加法運算: 開發工具
1 #include "stdafx.h" 2 #include <iostream> 3 4 class Complex //複數類 5 { 6 public: 7 double real;//實數 8 double imag;//虛數 9 Complex(double real=0,double imag=0) 10 { 11 this->real=real; 12 this->imag=imag; 13 } 14 }; 15 16 Complex operator+(Complex com1,Complex com2)//運算符重載函數 17 { 18 return Complex(com1.real+com2.real,com1.imag+com2.imag); 19 } 20 21 int main() 22 { 23 Complex com1(10,10),com2(20,20),sum; 24 sum=com1+com2;//或sum=operator+(com1,com2) 25 26 std::cout<<"sum的實數部分爲"<<sum.real<<std::endl; 27 std::cout<<"sum的虛數部分爲"<<sum.imag<<"i"<<std::endl; 28 29 return0; 30 }
結果: this
在上述示例代碼中,調用運算符重載函數時,也能夠以operator+(com1,com2)的形式來調用,實際上com1+com2在程序解釋時也是轉化成前者同樣的形式。可是直接用com1+com2的形式更加符合人的書寫習慣。 url
2.上述示例中的運算符重載函數是不屬於任何的類,是全局的函數。由於在Complex類(複數類)中的數據成員是公有的性質,因此運算符重載函數能夠訪問。但若是定義爲私有的呢,那該怎麼辦。其實,在實際的運算符重載函數聲明當中,要不定義其爲要操做類的成員函數或類的友元函數。 spa
(1)運算符重載函數做爲類的友元函數的形式: 指針
class 類名 code
{
friend 返回類型 operator運算符(形參表);
}
類外定義格式:
返回類型 operator運算符(參數表)
{
函數體
}
友元函數重載雙目運算符(有兩個操做數,一般在運算符的左右兩則),參數表中的個數爲兩個。如果重載單目運算符(只有一個操做數),則參數表中只有一參數。
i.友元函數重載雙目運算符(+):
1 #include "stdafx.h" 2 #include <iostream> 3 4 class Complex //複數類 5 { 6 private://私有 7 double real;//實數 8 double imag;//虛數 9 public: 10 Complex(double real=0,double imag=0) 11 { 12 this->real=real; 13 this->imag=imag; 14 } 15 friend Complex operator+(Complex com1,Complex com2);//友元函數重載雙目運算符+ 16 void showSum(); 17 }; 18 19 20 Complex operator+(Complex com1,Complex com2)//友元運算符重載函數 21 { 22 return Complex(com1.real+com2.real,com1.imag+com2.imag); 23 } 24 25 void Complex::showSum() 26 { 27 std::cout<<real; 28 if(imag>0) 29 std::cout<<"+"; 30 if(imag!=0) 31 std::cout<<imag<<"i"<<std::endl; 32 } 33 34 int main() 35 { 36 Complex com1(10,10),com2(20,-20),sum; 37 sum=com1+com2;//或sum=operator+(com1,com2) 38 sum.showSum();//輸出複數相加結果 39 40 return0; 41 }
結果:
ii.友元函數重載單目運算符(++):
1 #include "stdafx.h" 2 #include <iostream> 3 4 class Point//座標類 5 { 6 private: 7 int x; 8 int y; 9 public: 10 Point(int x,int y) 11 { 12 this->x=x; 13 this->y=y; 14 } 15 friend voidoperator++(Point& point);//友元函數重載單目運算符++ 16 void showPoint(); 17 }; 18 19 voidoperator++(Point& point)//友元運算符重載函數 20 { 21 ++point.x; 22 ++point.y; 23 } 24 25 void Point::showPoint() 26 { 27 std::cout<<"("<<x<<","<<y<<")"<<std::endl; 28 } 29 30 int main() 31 { 32 Point point(10,10); 33 ++point;//或operator++(point) 34 point.showPoint();//輸出座標值 35 36 return0; 37 }
結果:
運算符重載函數能夠返回任何類型,甚至是void,但一般返回類型都與它所操做的類類型同樣,這樣能夠使運算符使用在複雜的表達式中。好比把上述雙目運算符重載函數示例代碼中main()主函數裏的com1+com2改成com1+com2+com2,那麼結果又會不同了。像賦值運算符=、下標運算符[]、函數調用運算符()等是不能被定義爲友元運算符重載函數。同一個運算符能夠定義多個運算符重載函數來進行不一樣的操做。
(2)運算符重載函數做爲類的成員函數的形式:
class 類名
{
返回類型 operator 運算符(形參表);
}
類外定義格式:
返回類型 類名:: operator 運算符(形參表)
{
函數體;
}
對於成員函數重載運算符而言,雙目運算符的參數表中僅有一個參數,而單目則無參數。一樣的是重載,爲何和友元函數在參數的個數上會有所區別的。緣由在於友元函數,沒有this指針。
i.成員函數重載雙目運算符(+):
1 #include "stdafx.h" 2 #include <iostream> 3 4 class Complex //複數類 5 { 6 private://私有 7 double real;//實數 8 double imag;//虛數 9 public: 10 Complex(double real=0,double imag=0) 11 { 12 this->real=real; 13 this->imag=imag; 14 } 15 Complex operator+(Complex com1);//成員函數重載雙目運算符+ 16 void showSum(); 17 }; 18 19 20 Complex Complex::operator+(Complex com1) 21 { 22 return Complex(real+com1.real,imag+com1.imag); 23 } 24 25 void Complex::showSum() 26 { 27 std::cout<<real; 28 if(imag>0) 29 std::cout<<"+"; 30 if(imag!=0) 31 std::cout<<imag<<"i"<<std::endl; 32 } 33 34 35 int main() 36 { 37 Complex com1(10,10),com2(20,-20),sum; 38 sum=com1+com2;//或sum=com1.operator+(com2) 39 sum.showSum();//輸出複數相加結果 40 return0; 41 }
對於雙目運算符而言,運算符重載函數的形參中僅爲一個參數,它做爲運算符的右操做數(如com2對象),而當前對象做爲左操做數(如:上述中的com1對象),它是經過this指針隱含傳遞給成員運算符重載函數的。
ii.成員函數重載單目運算符(++):
1 #include "stdafx.h" 2 #include <iostream> 3 4 5 class Point//座標類 6 { 7 private: 8 int x; 9 int y; 10 public: 11 Point(int x,int y) 12 { 13 this->x=x; 14 this->y=y; 15 } 16 voidoperator++();//成員函數重載雙目運算符++ 17 void showPoint(); 18 }; 19 20 21 void Point::operator++() 22 { 23 ++x; 24 ++y; 25 } 26 27 28 void Point::showPoint() 29 { 30 std::cout<<"("<<x<<","<<y<<")"<<std::endl; 31 } 32 33 int main() 34 { 35 Point point(10,10); 36 ++point;//或point.operator++() 37 point.showPoint();//輸出座標值 38 39 return0; 40 }
對於單目運算符而言,當前對象做爲運算符的操做數。
在運算符重載運用時應該注意如下幾個問題:(1)C++中只能對已有的C++運算符進行重載,不容許用戶本身定義新的運算符;(2)C++中絕大部分的運算符可重載,除了成員訪問運算符.,成員指針訪問運算符.*,做用域運算符::,長度運算符sizeof以及條件運算符?:;(3)重載後不能改變運算符的操做對象(操做數)的個數。如:"+"是實現兩個操做數的運算符,重載後仍然爲雙目運算符;(4)重載不能改變運算符原有的優先級;(5)重載不能改變運算符原有結合的特性。好比:z=x/y*a,執行時是先作左結合的運算x/y,重載後也是如此,不會變成先作右結合y*a;(6)運算符重載不能所有是C++中預約義的基本數據,這樣作的目的是爲了防止用戶修改用於基本類型數據的運算符性質;(7)從上述的示例中能夠看到雙目運算符能夠被重載爲友元函數也能夠重載爲成員函數,但有一種狀況,只能使用友元函數,是什麼狀況呢?我舉個例子:
1 class Complex //複數類 2 { 3 private://私有 4 double real;//實數 5 double imag;//虛數 6 public: 7 Complex(double real=0,double imag=0) 8 { 9 this->real=real; 10 this->imag=imag; 11 } 12 Complex operator+(int x); 13 }; 14 15 Complex Complex::operator+(int x) 16 { 17 return Complex(real+x,imag); 18 } 19 20 int main() 21 { 22 Complex com1(5,10),total; 23 total=com1+5; 24 25 return0; 26 }
若是咱們把上述main()主函數實現部分裏的total=com1+5改成total=5+com1;那麼程序就會報錯(沒有與這些操做數匹配的 "+" 運算符),由於左操做數5不是該複數類的對象,不能調用相應的成員函數Complex operator+(int x),因此編譯錯誤。但若是咱們定義一下兩個友元函數就能解決上述的問題:
friend Complex operator+(Complex com1,int x);
friend Complex operator+(int x,Complex com1);
3.最後仍是同樣,我將用一個示例來總結一下今天所講的內容(開發工具:vs2010):
1 #include "stdafx.h" 2 #include <iostream> 3 4 class Complex //複數類 5 { 6 private://私有 7 double real;//實數 8 double imag;//虛數 9 public: 10 Complex(double real=0,double imag=0) 11 { 12 this->real=real; 13 this->imag=imag; 14 } 15 Complex operator+(Complex com1);//成員函數重載雙目運算符+ 16 //或friend Complex operator+(Complex com1,Complex com2);//友元函數重載雙目運算符+ 17 friend Complex operator+(Complex com1,int x);//友元函數重載雙目運算符+ 18 //或Complex operator+(int x); 19 friend Complex operator+(int x,Complex com1);//友元函數重載雙目運算符+ 20 void showSum(); 21 }; 22 23 24 Complex Complex::operator+(Complex com1) 25 { 26 return Complex(real+com1.real,imag+com1.imag); 27 } 28 29 Complex operator+(Complex com1,int x)//左操做數類型爲複數,右操做數的類型爲整數 30 { 31 return Complex(com1.real+x,com1.imag); 32 } 33 34 Complex operator+(int x,Complex com1)//左操做數類型爲整數,右操做數的類型爲複數 35 { 36 return Complex(x+com1.real,com1.imag); 37 } 38 39 void Complex::showSum() 40 { 41 std::cout<<real; 42 if(imag>0) 43 std::cout<<"+"; 44 if(imag!=0) 45 std::cout<<imag<<"i"<<std::endl; 46 } 47 48 class Point//座標類 49 { 50 private: 51 int x; 52 int y; 53 public: 54 Point(int x,int y) 55 { 56 this->x=x; 57 this->y=y; 58 } 59 friend voidoperator++(Point& point);//友元函數重載單目運算符++ 60 Point operator++();//成員函數重載雙目運算符++ 61 void showPoint(); 62 }; 63 64 voidoperator++(Point& point)//友元運算符重載函數 65 { 66 ++point.x; 67 ++point.y; 68 } 69 70 Point Point::operator++() 71 { 72 ++x; 73 ++y; 74 return*this;//返回當前對象 75 } 76 77 78 void Point::showPoint() 79 { 80 std::cout<<"("<<x<<","<<y<<")"<<std::endl; 81 } 82 83 int main() 84 { 85 //兩個複數相加 86 std::cout<<"兩個複數相加:"<<std::endl; 87 88 Complex com1(10,10),com2(20,-20),sum; 89 sum=com1+com2;//或sum=com1.operator+(com2) 90 std::cout<<"(10+10i)+(20-20i)="; 91 sum.showSum();//輸出複數相加結果 92 93 //三個複數相加 94 std::cout<<"三個複數相加:"<<std::endl; 95 96 sum=com1+com2+com2; 97 std::cout<<"(10+10i)+(20-20i)+(20-20i)="; 98 sum.showSum(); 99 100 //整數和複數相加 101 std::cout<<"整數和複數相加:"<<std::endl; 102 103 Complex com3(5,10),total; 104 total=com3+5;//或total=operator+(com1,5); 105 std::cout<<"(5+10i)+5="; 106 total.showSum(); 107 108 total=5+com3;//或total=operator+(5,com1); 109 //只能用友元函數來重載運算符 110 std::cout<<"5+(5+10i)="; 111 total.showSum(); 112 113 //單目運算符++重載 114 std::cout<<"單目運算符++重載:"<<std::endl; 115 116 //注意:下述實現部分不能只用一個++point會形成二義性 117 Point point(10,10); 118 //調用友元函數 119 operator++(point);//或++point 120 std::cout<<"調用友元函數:++(10,10)="; 121 point.showPoint();//輸出座標值 122 123 //調用成員函數 124 point=point.operator++();//或++point; 125 std::cout<<"調用成員函數:++(10,10)="; 126 point.showPoint(); 127 128 return0; 129 }
結果: