1、重載二元操作符的方法
二元運算符又稱為雙目運算符,即需要2個操作數的運算符,例如 + - * / 等。
運算符重載可以分為3種方式:類的非靜態成員函數、類的友元函數、普通函數。
例如有 2 個操作數 a 和 b,二元運算符 ? (表示一個二元運算符),a ? b 的操作會被解釋為下面2種形式之一
//a ? b a.operator?(b); //類的非靜態成員函數 operator?(a, b); //友元函數 和 普通函數
第一種形式是運算符被重載為類的非靜態成員函數,
這種方式要求運算符左邊的的操作數(即第一個操作數a)必須是一個對象,operator?是這個對象的非靜態成員函數
並且只能有一個參數。
第二種形式是運算符被重載為類的友元函數 或 普通函數,
這種方式需要2個參數,
重載為 類的友元函數 和 普通函數的區別是 類的友元函數可以直接訪問類的私有成員,而普通函數不可以。
2、應用舉例(對象 ? 對象)
下例中有3個complex類 ComplexA、ComplexB 和 ComplexC,3個類都重載了加減乘除 運算符。
其中ComplexA使用類的非靜態成員函數方式重載,ComplexB使用類的友元函數方式重載,ComplexC使用普通函數方式重載。
需要注意的是復數的加減乘除運算的算法是有問題的,只是一個說明重載方法的例子,
另外重載函數的參數最好使用const關鍵字限定,至於返回值是否用const限定,需要取決於你的設計,比如允許C3 = ++(C1+C2)這種情況,就不能用cosnt限定。
至於不同類型的對象間的操作,通常是沒有意義的。
#include <iostream> using namespace std; class ComplexA { public: //默認構造函數(Default constructor) ComplexA(){cout<<"Default Constructor"<<endl;} //帶參數的構造函數(The constructor with parameters) ComplexA(double re, double im):real(re),image(im){cout<<"Parameter Constructor"<<endl;} //拷貝構造函數(Copy constructor) ComplexA(const ComplexA& ref){real = ref.real; image = ref.image; cout<<"Copy Constructor"<<endl;} //析構函數(destructor) ~ComplexA(){cout<<"Destructor"<<endl;} //Operator Overload : + ComplexA operator+(ComplexA& ref) { return ComplexA(real + ref.real, image + ref.image); } //Operator Overload : - ComplexA operator-(ComplexA& ref) { return ComplexA(real - ref.real, image - ref.image); } //Operator Overload : * ComplexA operator*(ComplexA& ref) { return ComplexA(real * ref.real, image * ref.image); } //Operator Overload : / ComplexA operator/(ComplexA& ref) { return ComplexA(real / ref.real, image / ref.image); } //display void display(void){cout<<real<<"+"<<image<<"i"<<endl;} private: double real; //復數的實部 double image; //復數的虛部 }; class ComplexB { public: //默認構造函數(Default constructor) ComplexB(){cout<<"Default Constructor"<<endl;} //帶參數的構造函數(The constructor with parameters) ComplexB(double re, double im):real(re),image(im){cout<<"Parameter Constructor"<<endl;} //拷貝構造函數(Copy constructor) ComplexB(const ComplexB& ref){real = ref.real; image = ref.image; cout<<"Copy Constructor"<<endl;} //析構函數(destructor) ~ComplexB(){cout<<"Destructor"<<endl;} //Operator Overload : + friend ComplexB operator+(ComplexB& ref1, ComplexB& ref2) { return ComplexB(ref1.real + ref2.real, ref1.image + ref2.image); } //Operator Overload : - friend ComplexB operator-(ComplexB& ref1, ComplexB& ref2) { return ComplexB(ref1.real - ref2.real, ref1.image - ref2.image); } //Operator Overload : * friend ComplexB operator*(ComplexB& ref1, ComplexB& ref2) { return ComplexB(ref1.real * ref2.real, ref1.image * ref2.image); } //Operator Overload : / friend ComplexB operator/(ComplexB& ref1, ComplexB& ref2) { return ComplexB(ref1.real / ref2.real, ref1.image / ref2.image); } //display void display(void){cout<<real<<"+"<<image<<"i"<<endl;} private: double real; //復數的實部 double image; //復數的虛部 }; class ComplexC { public: //默認構造函數(Default constructor) ComplexC(){cout<<"Default Constructor"<<endl;} //帶參數的構造函數(The constructor with parameters) ComplexC(double re, double im):real(re),image(im){cout<<"Parameter Constructor"<<endl;} //拷貝構造函數(Copy constructor) ComplexC(const ComplexC& ref){real = ref.real; image = ref.image; cout<<"Copy Constructor"<<endl;} //析構函數(destructor) ~ComplexC(){cout<<"Destructor"<<endl;} //Get Data double GetReal(void){return real;} double GetImage(void){return image;}
//display void display(void){cout<<real<<"+"<<image<<"i"<<endl;} private: double real; //復數的實部 double image; //復數的虛部 }; //Operator Overload : + ComplexC operator+(ComplexC& ref1, ComplexC& ref2) { return ComplexC(ref1.GetReal() + ref2.GetReal(), ref1.GetImage() + ref2.GetImage()); } //Operator Overload : - ComplexC operator-(ComplexC& ref1, ComplexC& ref2) { return ComplexC(ref1.GetReal() - ref2.GetReal(), ref1.GetImage() - ref2.GetImage()); } //Operator Overload : * ComplexC operator*(ComplexC& ref1, ComplexC& ref2) { return ComplexC(ref1.GetReal() * ref2.GetReal(), ref1.GetImage() * ref2.GetImage()); } //Operator Overload : / ComplexC operator/(ComplexC& ref1, ComplexC& ref2) { return ComplexC(ref1.GetReal() / ref2.GetReal(), ref1.GetImage() / ref2.GetImage()); } int main(void) { ComplexA C1(2,4), C2(1, 2), C3; C3 = C1 + C2; C3.display(); C3 = C1 - C2; C3.display(); C3 = C1 * C2; C3.display(); C3 = C1 / C2; C3.display(); cout <<"--------------------------------------"<<endl; ComplexB C4(2,4), C5(1, 2), C6; C6 = C4 + C5; C6.display(); C6 = C4 - C5; C6.display(); C6 = C4 * C5; C6.display(); C6 = C4 / C5; C6.display(); cout <<"--------------------------------------"<<endl; ComplexC C7(2,4), C8(1, 2), C9; C9 = C7 + C8; C9.display(); C9 = C7 - C8; C9.display(); C9 = C7 * C8; C9.display(); C9 = C7 / C8; C9.display(); return 0; }
3、應用舉例(對象 ? 基本數據類型 or 基本數據類型 ? 對象)
上面的例子中是對象 和 對象之間的運算符重載,如果需要一個是對象 + char/int/float/double,或者反過來 char/int/float/double + 對象,這時上面的程序的重載方式就不適用了。
需要定義新的重載,如下列程序所示。
#include <iostream> using namespace std; class ComplexD { public: ComplexD(double re = 0, double im = 0):real(re),image(im){} ComplexD operator+(ComplexD& ref){return ComplexD(real+ref.real, image+ref.image);}; ComplexD operator+(int a){cout<<"IN\t int \t\t";return ComplexD(real+a, image);}; ComplexD operator+(double d){cout<<"IN\t double \t";return ComplexD(real+d, image);}; ComplexD operator+(float f){cout<<"IN\t float \t\t";return ComplexD(real+f, image);}; void display(void){cout<<real<<"+"<<image<<"i"<<endl;} double GetReal(void){return real;} double GetImage(void){return image;} private: double real; double image; }; ComplexD operator+(int a, ComplexD& ref){cout<<"OUT\t int \t\t";return ComplexD(ref.GetReal()+a, ref.GetImage());}; ComplexD operator+(double d, ComplexD& ref){cout<<"OUT\t double \t";return ComplexD(ref.GetReal()+d, ref.GetImage());}; ComplexD operator+(float f, ComplexD& ref){cout<<"OUT\t float \t\t";return ComplexD(ref.GetReal()+f, ref.GetImage());}; int main(void) { ComplexD D1(2,4), D2; D2 = D1 + 2; D2.display(); D2 = D1 + 2.1f; D2.display(); D2 = D1 + 2.1; D2.display(); D2 = 2 +D1; D2.display(); D2 = 2.1f + D1; D2.display(); D2 = 2.1 +D1; D2.display(); return 0; }