0、重載一元操作符的方法
一元運算符即只需要一個操作用的運算符,如取地址運算符(&)、復數(-)、自減(--)、自加(++)等。
運算符重載可以分為3種方式:類的非靜態成員函數、類的友元函數、普通函數。
例如有 1 個操作數 a,一元運算符 ? (表示一個一元運算符),a? 或者?a 的操作會被解釋為下面2種形式之一
//a? or ?a a.operator?(); //類的非靜態成員函數 operator?(a); //友元函數 和 普通函數
第一種形式是運算符被重載為類的非靜態成員函數,沒有參數。
這種方式要求操作數(即a)必須是一個對象,operator?是這個對象的非靜態成員函數,
第二種形式是運算符被重載為類的友元函數 或 普通函數,有1個參數。
重載為 類的友元函數 和 普通函數的區別是 類的友元函數可以直接訪問類的私有成員,而普通函數不可以。
1、重載++、--(前置 和 后置)
自增運算符(++)和 自減運算符(--)都有 前置 和 后置 2中情況。
C++中為了區分前置和后置規定:前置重載與普通運算符重載一致,后置重載需要在參數列表中加入一個無用的參數。
++/-- 的3種重載方式如下: 前置的情況可以返回類的引用,后置的情況只能返回臨時對象。
//類的非靜態成員函數 class X { X& operator++(){...} //前置++ X operator++(int){...} //后置++ X& operator--(){...} //前置-- X operator--(int){...} //后置-- } /*-----------------------------------------------------*/ //類的友元函數 class X { friend X& operator++(X& ref){...} //前置++ friend X operator++(X& ref, int){...} //后置++ friend X& operator--(X& ref){...} //前置-- friend X operator--(X& ref, int){...} //后置-- } /*-----------------------------------------------------*/ //普通函數 class X { ... } X& operator++(X& ref){...} //前置++ X operator++(X& ref, int){...} //后置++ X& operator--(X& ref){...} //前置-- X operator--(X& ref, int){...} //后置--
下例中有3個Counter類 CounterA、CounterB 和CounterC,3個類都重載了前置++、-- 和后置++、--。
其中CounterA使用類的非靜態成員函數方式重載,CounterB使用類的友元函數方式重載,CounterC使用普通函數方式重載。
#include <iostream> using namespace std; class CounterA { public: //默認構造函數(Default constructor) CounterA(){cout<<"Default Constructor"<<endl;} //帶參數的構造函數(The constructor with parameters) CounterA(int m):n(m){cout<<"Parameter Constructor"<<endl;} //拷貝構造函數(Copy constructor) CounterA(const CounterA& ref){n = ref.n; cout<<"Copy Constructor"<<endl;} //析構函數(destructor) ~CounterA(){cout<<"Destructor"<<endl;} //重載運算符 ++(前置) const CounterA& operator++(){++n; return *this;} //重載運算符 ++(后置) const CounterA operator++(int dump){CounterA Tmp(*this);++n; return Tmp;} //重載運算符 --(前置) const CounterA& operator--(){--n; return *this;} //重載運算符 --(后置) const CounterA operator--(int dump){CounterA Tmp(*this);--n; return Tmp;} //輸出用函數 void display(void){cout<<"n = " << n << endl;} //GetData int GetVal(void){return n;} private: int n; }; class CounterB { public: //默認構造函數(Default constructor) CounterB(){cout<<"Default Constructor"<<endl;} //帶參數的構造函數(The constructor with parameters) CounterB(int m):n(m){cout<<"Parameter Constructor"<<endl;} //拷貝構造函數(Copy constructor) CounterB(const CounterB& ref){n = ref.n; cout<<"Copy Constructor"<<endl;} //析構函數(destructor) ~CounterB(){cout<<"Destructor"<<endl;} //重載運算符 ++(前置) friend const CounterB& operator++(CounterB& ref){ref.n += 1;return ref;} //重載運算符 ++(后置) friend const CounterB operator++(CounterB& ref, int dump){CounterB Tmp(ref);ref.n += 1; return Tmp;} //重載運算符 --(前置) friend const CounterB& operator--(CounterB& ref){ref.n -= 1;return ref;} //重載運算符 --(后置) friend const CounterB operator--(CounterB& ref, int dump){CounterB Tmp(ref);ref.n -= 1; return Tmp;} //輸出用函數 void display(void){cout<<"n = " << n << endl;} //GetData int GetVal(void){return n;} //SetData void SetVal(int val){n = val;} private: int n; }; class CounterC { public: //默認構造函數(Default constructor) CounterC(){cout<<"Default Constructor"<<endl;} //帶參數的構造函數(The constructor with parameters) CounterC(int m):n(m){cout<<"Parameter Constructor"<<endl;} //拷貝構造函數(Copy constructor) CounterC(const CounterC& ref){n = ref.n; cout<<"Copy Constructor"<<endl;} //析構函數(destructor) ~CounterC(){cout<<"Destructor"<<endl;} //輸出用函數 void display(void){cout<<"n = " << n << endl;} //GetData int GetVal(void){return n;} //SetData void SetVal(int val){n = val;} private: int n; }; //重載運算符 ++(前置) const CounterC& operator++(CounterC& ref){ref.SetVal(ref.GetVal()+1);return ref;} //重載運算符 ++(后置) const CounterC operator++(CounterC& ref, int dump){CounterC Tmp(ref);ref.SetVal(ref.GetVal()+1); return Tmp;} //重載運算符 --(前置) const CounterC& operator--(CounterC& ref){ref.SetVal(ref.GetVal()-1);return ref;} //重載運算符 --(后置) const CounterC operator--(CounterC& ref, int dump){CounterC Tmp(ref);ref.SetVal(ref.GetVal()-1); return Tmp;} int main(void) { CounterA cp1(5);cp1.display(); ++cp1;cp1.display(); --cp1;cp1.display(); CounterA cp2(cp1++);cp2.display(); CounterA cp3(cp1--);cp3.display(); CounterB cp4(5);cp4.display(); ++cp4;cp4.display(); --cp4;cp4.display(); CounterB cp5(cp4++);cp5.display(); CounterB cp6(cp4--);cp6.display(); CounterC cp7(5);cp7.display(); ++cp7;cp7.display(); --cp7;cp7.display(); CounterC cp8(cp7++);cp8.display(); CounterC cp9(cp7--);cp9.display(); return 0; }
2、重載負號(-)
下例中有3個Complex類 ComplexA、ComplexB 和ComplexC,3個類都重載了負號。
其中ComplexA使用類的非靜態成員函數方式重載,ComplexB使用類的友元函數方式重載,ComplexC使用普通函數方式重載。
#include <iostream> using namespace std; class ComplexA { public: //constructor ComplexA(double re, double im):real(re),image(im){} //Operator Overload : - ComplexA operator-(){return ComplexA(-real, -image);} //display void display(void){if (image>0)cout<<real<<"+"<<image<<endl;else cout<<real<<image<<endl;} private: double real; double image; }; class ComplexB { public: //constructor ComplexB(double re, double im):real(re),image(im){} //Operator Overload : - friend ComplexB operator-(ComplexB& ref){return ComplexB(-ref.real, -ref.image);} //display void display(void){if (image>0)cout<<real<<"+"<<image<<endl;else cout<<real<<image<<endl;} private: double real; double image; }; class ComplexC { public: //constructor ComplexC(double re, double im):real(re),image(im){} //GetData double GetReal(void){return real;} double GetImage(void){return image;} //display void display(void){if (image>0)cout<<real<<"+"<<image<<endl;else cout<<real<<image<<endl;} private: double real; double image; }; //Operator Overload : - ComplexC operator-(ComplexC& ref){return ComplexC(-ref.GetReal(), -ref.GetImage());} int main(void) { ComplexA a1(1,2);a1.display(); ComplexA a2(-a1);a2.display(); ComplexB b1(1,2);b1.display(); ComplexB b2(-b1);b2.display(); ComplexC c1(1,2);c1.display(); ComplexC c2(-c1);c2.display(); return 0; }
