=
要求左右兩個運算元的型別是匹配的,或至少是相容的。有時希望=
兩邊的運算元的型別即使不相容也能夠成立,這就需要對=
進行過載。C++ 規定,=
只能過載為成員函數。來看下面的例子。
結尾的字串。String 類可以如下編寫:
#include <iostream> #include <cstring> using namespace std; class String { private: char * str; public: String() :str(NULL) { } const char * c_str() const { return str; }; String & operator = (const char * s); ~String(); }; String & String::operator = (const char * s) //過載"="以使得 obj = "hello"能夠成立 { if (str) delete[] str; if (s) { //s不為NULL才會執行拷貝 str = new char[strlen(s) + 1]; strcpy(str, s); } else str = NULL; return *this; } String::~String() { if (str) delete[] str; }; int main() { String s; s = "Good Luck,"; //等價於 s.operator=("Good Luck,"); cout << s.c_str() << endl; // String s2 = "hello!"; //這條語句要是不注釋掉就會出錯 s = "Shenzhou 8!"; //等價於 s.operator=("Shenzhou 8!"); cout << s.c_str() << endl; return 0; }程式的執行結果:
char* p = s.c_str (); strcpy(s.c_str(), "Tiangong1");第一條語句出錯是因為
=
左邊是 char* 型別,右邊是 const char * 型別,兩邊型別不匹配;第二條語句出錯是因為 strcpy 函數的第一個形參是 char* 型別,而這裡實參給出的卻是 const char * 型別,同樣型別不匹配。=
的過載,第 34 行的s = "Good Luck,"
肯定會因為型別不匹配而編譯出錯。經過過載後,第 34 行等價於s.operator=("Good Luck,");
,就沒有問題了。
,因此分配的位元組數要比 strlen(s) 多 1。String s2 = "hello!";
還是會編譯出錯,因為這是一條初始化語句,要用到建構函式,而不是賦值運算子=。String 類沒有編寫引數型別為 char * 的建構函式,因此編譯不能通過。a = b = c;
假定 a、b、c 都是 String 物件,則上面的語句等價於下面的巢狀函數呼叫:a.operator=( b.operator=(c) );
如果 operator= 函數的返回值型別為 void,顯然上面這個巢狀函數呼叫就不能成立。將返回值型別改為 String 並且返回 *this 可以解決問題,但是還不夠好。因為,假設 a、b、c 是基本型別的變數,則(a =b) = c;
這條語句執行的效果會使得 a 的值和 c 相等,即a = b
這個表示式的值其實是 a 的參照。為了保持=的這個特性,operator= 函數也應該返回其所作用的物件的參照。因此,返回值型別為 String & 才是風格最好的寫法。在 a、b、c 都是 String 物件時,(a=b)=c;
等價於
( a.operator=(b) ).operator=(c);
a.operator=(b) 返回對 a 的參照後,通過該參照繼續呼叫 operator=(c),就會改變 a 的值。