天天看點

C++中重載運算符的使用

C++中重載運算符的使用:

使用者定義的類型,如:字元串,日期,複數,聯合體以及檔案常常重載二進制 + 操作符以實作對象的連接配接,附加或合并機制。但是要正确實作 + 操作符會給設計,實作和性能帶來一定的挑戰。本文将概要性地介紹如何選擇正确的政策來為使用者定義類型重載這個操作符。

考慮如下的表達式: int x=4+2;

内建的 + 操作符有兩個類型相同的操作數,相加并傳回右值 6,然後被指派給 x。我們可以斷定内建的 + 是一個二進制的,對稱的,可交換的操作符。它産生的結果的類型與其操作數類型相同。按照這個規測,當你為某個使用者定義類型重載操作符時,也應該遵循相應内建操作符的特征。

為使用者定義類型重載 + 操作符是很常見的程式設計任務。盡管 C++ 提供了幾種實作方法,但是它們容易使人産生設計上的誤解,這種誤解常常影響代碼的正确性,性能以及與标準庫元件之間的相容性。

下面我們就來分析内建操作符的特征并嘗試模仿其相應的重載機制。

C++中重載運算符的使用

C++中重載運算符的使用

第一步:在成員函數和非成員函數之間選擇

你可以用類成員函數的方式實作二進制操作符如:+、- 以及 ==,例如:

class String

{

public:

bool operator==(const String & s); // 比較 *this 和 s

};

這個方法是有問題的。相對于其内建的操作符來說,重載的操作符在這裡不具有對稱性;它的兩個參數一個類型為:const String * const(這個參數是隐含的),另一個類型為:const String &。是以,一些 STL 算法和容器将無法正确處理這樣的對象。

另外一個可選方法是把重載操作符 + 定義為一個外部(extern)函數,該函數帶兩個類型相同的參數:

String operator + (const String & s1, const String s2);

這樣一來,類 String 必須将該重載操作符聲明為友元:

friend String operator+(const String& s1,const String&s2);

第二步:傳回值的兩難選擇

如前所述,内建操作符 + 傳回右值,其類型與操作數相同。但是在調用者堆棧裡傳回一個對象效率很低,處理大型對象時尤其如此。那麼能不能傳回一個指針或引用呢?答案是不行。因為傳回指針破壞參數類型與傳回值類型應該相同的規則。更糟的是,連結多個表達式将成為不可能:

String s1,s2,s3;

String res;

res=s1+s2+s3; // 不可能用 String* 作為傳回值

雖然有一個辦法可以定義額外的 + 操作符重載版本,但這個辦法是我們不希望用的,因為傳回的指針必須指向動态配置設定的對象。這樣的話,如果調用者釋放(delete)傳回的指針失敗,那麼将導緻記憶體洩漏。顯然,傳回 String* 不是一個好主意。

那麼傳回 String& 好不好呢?傳回的引用必須一定要是一個有效的 String。它避免了使用動态對象配置設定,該方法傳回的是一個本地靜态對象的引用。靜态對象确實解決了記憶體洩漏問題,但這個方法的可行性仍然值得懷疑。在一個多線程應用中,兩個線程可能會并發調用 + 操作符,是以造成 String 對象的混亂。而且,因為靜态對象總是保留其調用前的狀态,是以有必要針對每次 + 操作符的調用都清除該靜态 String 對象。由此看來,在堆棧上傳回結果仍然是最安全和最簡單的解決方案。

繼續閱讀