詳解C++編程中的單目運算符重載與雙目運算符重載
C++單目運算符重載
單目運算符只有一個操作數,如!a,-b,&c,*p,還有最常用的++i和--i等。重載單目運算符的方法與重載雙目運算符的方法是類似的。但由于單目運算符只有一個操作數,因此運算符重載函數只有一個參數,如果運算符重載函數作為成員函數,則還可省略此參數。
下面以自增運算符”++“為例,介紹單目運算符的重載。
[例] 有一個Time類,包含數據成員minute(分)和sec(秒),模擬秒表,每次走一秒,滿60秒進一分鐘,此時秒又從0開始算。要求輸出分和秒的值。
#include <iostream>
using namespace std;
class Time
{
public:
Time( ){minute=0;sec=0;} //默認構造函數
Time(int m,int s):minute(m),sec(s){ } //構造函數重載
Time operator++( ); //聲明運算符重載函數
void display( ){cout<<minute<<":"<<sec<<endl;} //定義輸出時間函數
private:
int minute;
int sec;
};
Time Time::operator++( ) //定義運算符重載函數
{
if(++sec>=60)
{
sec-=60; //滿60秒進1分鐘
++minute;
}
return *this; //返回當前對象值
}
int main( )
{
Time time1(34,0);
for (int i=0;i<61;i++)
{
++time1;
time1.display( );
}
return 0;
}
運行情況如下:
34:1 34:2 ┆ 34:59 35:0 35:1 (共輸出61行)
可以看到:在程序中對運算符“++”進行了重載,使它能用于Time類對象。“++”和“--”運算符有兩種使用方式,前置自增運算符和后置自增運算符,它們的作用是不一樣的,在重載時怎樣區(qū)別這二者呢?
針對“++”和“--”這一特點,C++約定,在自增(自減)運算符重載函數中,增加一個int型形參,就是后置自增(自減)運算符函數。
[例] 在上面例子程序的基礎上增加對后置自增運算符的重載。修改后的程序如下:
#include <iostream>
using namespace std;
class Time
{
public:
Time( ){minute=0;sec=0;}
Time(int m,int s):minute(m),sec(s){}
Time operator++( );//聲明前置自增運算符“++”重載函數
Time operator++(int);//聲明后置自增運算符“++”重載函數
void display( ){cout<<minute<<":"<<sec<<endl;}
private:
int minute;
int sec;
};
Time Time::operator++( )//定義前置自增運算符“++”重載函數
{
if(++sec>=60)
{
sec-=60;
++minute;
}
return *this;//返回自加后的當前對象
}
Time Time::operator++(int)//定義后置自增運算符“++”重載函數
{
Time temp(*this);
sec++;
if(sec>=60)
{
sec-=60;
++minute;
}
return temp; //返回的是自加前的對象
}
int main( )
{
Time time1(34,59),time2;
cout<<" time1 : ";
time1.display( );
++time1;
cout<<"++time1: ";
time1.display( );
time2=time1++; //將自加前的對象的值賦給time2
cout<<"time1++: ";
time1.display( );
cout<<" time2 :";
time2.display( ); //輸出time2對象的值
}
請注意前置自增運算符“++”和后置自增運算符“++”二者作用的區(qū)別。前者是先自加,返回的是修改后的對象本身。后者返回的是自加前的對象,然后對象自加。請仔細分析后置自增運算符重載函數。
運行結果如下:
time1 : 34:59(time1原值) ++time1: 35:0 (執(zhí)行++time1后time1的值) time1++: 35:1 (再執(zhí)行time1++后time1的值) time2 : 35:0 (time2保存的是執(zhí)行time1++前time1的值)
可以看到,重載后置自增運算符時,多了一個int型的參數,增加這個參數只是為了與前置自增運算符重載函數有所區(qū)別,此外沒有任何作用。編譯系統(tǒng)在遇到重載后置自增運算符時,會自動調用此函數。
C++雙目運算符重載
雙目運算符(或稱二元運算符)是C++中最常用的運算符。雙目運算符有兩個操作數,通常在運算符的左右兩側,如3+5,a=b,i<10等。在重載雙目運算符時,不言而喻在函數中應該有兩個參數。
[例] 定義一個字符串類String,用來存放不定長的字符串,重載運算符“==”、“<”和“>”,用于兩個字符串的等于、小于和大于的比較運算。
為了使讀者便于理解程序,同時也使讀者了解建立程序的步驟,下面分幾步來介紹編程過程:
1) 先建立一個String類:
#include <iostream>
using namespace std;
class String
{
public:
String( ){p=NULL;} //默認構造函數
String(char *str); //構造函數
void display( );
private:
char *p;//字符型指針,用于指向字符串
};
String::String(char *str) //定義構造函數
{p=str;} //使p指向實參字符串
void String::display( ) //輸出p所指向的字符串
{cout<<p;}
int main( )
{
String string1("Hello"),string2("Book");
string1.display( );
cout<<endl;
string2.display( );
return 0;
}
運行結果為:
Hello Book
2) 有了這個基礎后,再增加其他必要的內容?,F在增加對運算符重載的部分。為便于編寫和調試,先重載一個運算符“>”。程序如下:
#include <iostream>
#include <string>
using namespace std;
class String
{
public:
String( ){p=NULL;}
String(char *str);
friend bool operator>(String &string1,String &string2);//聲明運算符函數為友元函數
void display( );
private:
char *p;//字符型指針,用于指向字符串
};
String::String(char *str)
{p=str;}
void String::display( ) //輸出p所指向的字符串
{cout<<p;}
bool operator>(String &string1,String &string2)//定義運算符重載函數
{
if(strcmp(string1.p,string2.p)>0)
return true;
else return false;
}
int main( )
{
String string1("Hello"),string2("Book");
cout<<(string1>string2)<<endl;
}
程序運行結果為1。
這只是一個并不很完善的程序,但是,已經完成了實質性的工作了,運算符重載成功了。其他兩個運算符的重載如法炮制即可。
3) 擴展到對3個運算符重載。
在String類體中聲明3個成員函數:
friend bool operator> (String &string1, String &string2); friend bool operator< (String &string1, String &string2); friend bool operator==(String &string1, String& string2);
在類外分別定義3個運算符重載函數:
bool operator>(String &string1,String &string2) //對運算符“>”重載
{
if(strcmp(string1.p,string2.p)>0)
return true;
else
return false;
}
bool operator<(String &string1,String &string2) //對運算符“<”重載
{
if(strcmp(string1.p,string2.p)<0)
return true;
else
return false;
}
bool operator==(String &string1,String &string2) //對運算符“==”重載
{
if(strcmp(string1.p,string2.p)==0)
return true;
else
return false;
}
再修改主函數:
int main( )
{
String string1("Hello"), string2("Book"), string3("Computer");
cout<<(string1>string2)<<endl; //比較結果應該為true
cout<<(string1<string3)<<endl; //比較結果應該為false
cout<<(string1==string2)<<endl; //比較結果應該為false
return 0;
}
運行結果為:
1 0 0
結果顯然是對的。到此為止,主要任務基本完成。
4) 再進一步修飾完善,使輸出結果更直觀。下面給出最后的程序。
#include <iostream>
using namespace std;
class String
{
public:
String( ){p=NULL;}
String(char *str);
friend bool operator>(String &string1, String &string2);
friend bool operator<(String &string1, String &string2);
friend bool operator==(String &string1, String &string2);
void display( );
private:
char *p;
};
String::String(char *str)
{p=str;}
void String::display( ) //輸出p所指向的字符串
{cout<<p;}
bool operator>(String &string1, String &string2)
{
if(strcmp(string1.p, string2.p)>0)
return true;
else
return false;
}
bool operator<(String &string1, String &string2)
{
if(strcmp(string1.p, string2.p)<0)
return true;
else
return false;
}
bool operator==(String &string1, String &string2)
{
if(strcmp(string1.p, string2.p)==0)
return true;
else
return false;
}
void compare(String &string1, String &string2)
{
if(operator>(string1, string2)==1)
{string1.display( );cout<<">";string2.display( );}
else
if(operator<(string1, string2)==1)
{string1.display( );cout<<"<";string2.display( );}
else
if(operator==(string1, string2)==1)
{string1.display( );cout<<"=";string2.display( );}
cout<<endl;
}
int main( )
{
String string1("Hello"), string2("Book"), string3("Computer"), string4("Hello");
compare(string1, string2);
compare(string2, string3);
compare(string1, string4);
return 0;
}
運行結果為:
Hello>Book Book<Computer Hello==Hello
增加了一個compare函數,用來對兩個字符串進行比較,并輸出相應的信息。這樣可以減輕主函數的負擔,使主函數簡明易讀。
通過這個例子,不僅可以學習到有關雙目運算符重載的知識,而且還可以學習怎樣去編寫C++程序。由于C ++程序包含類,一般都比較長,有的初學C++的讀者見到比較長的程序就發(fā)怵,不知該怎樣著手去閱讀和分析它。輪到自己編程序,更不知道從何入 手,往往未經深思熟慮,想到什么就寫什么,一口氣把程序寫了出來,結果一運行,錯 誤百出,光為找出錯位置就花費了大量的時間。根據許多初學者的經驗,上面介紹的方法是很適合沒有編程經驗的初學者的,能使人以清晰的思路進行程序設計,減少出錯機會, 提高調試效率。
這種方法的指導思想是:先搭框架,逐步擴充,由簡到繁,最后完善。邊編程,邊調試,邊擴充。千萬不要企圖在一開始時就解決所有的細節(jié)。類是可擴充的,可以一步一步地擴充它的功能。最好直接在計算機上寫程序,每一步都要上機調試,調試通過了前面一步再做下一步,步步為營。這樣編程和調試的效率是比較高的。大家可以試驗一下。

