| 導購 | 订阅 | 在线投稿
分享
 
 
 

C++ 中重載 + 操作符的正確方法

來源:互聯網  2008-06-01 02:03:15  評論

用戶定義的類型,如:字符串,日期,複數,聯合體以及文件經常重載二元 + 操作符以實現對象的連接,附加或合並機制。但是要正確實現 + 操作符會給設計,實現和性能帶來一定的挑戰。本文將概要性地介紹如何選擇正確的策略來爲用戶定義類型重載這個操作符。

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

內建的 + 操作符有兩個類型相同的操作數,相加並返回右值 6,然後被賦值給 x。我們可以斷定內建的 + 是一個二元的,對稱的,可交換的操作符。它産生的結果的類型與其操作數類型相同。按照這個規測,當你爲某個用戶定義類型重載操作符時,也應該遵循相應內建操作符的特征。

爲用戶定義類型重載 + 操作符是很常見的編程任務。盡管 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 必須將該重載操作符聲明爲友元:

class String

{

public:

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 對象。由此看來,在堆棧上返回結果仍然是最安全和最簡單的解決方案。

C++ 中重載 + 操作符的正確方法
更多內容請看C/C++技術專題 C/C++進階技術文檔專題,或

用戶定義的類型,如:字符串,日期,複數,聯合體以及文件經常重載二元 + 操作符以實現對象的連接,附加或合並機制。但是要正確實現 + 操作符會給設計,實現和性能帶來一定的挑戰。本文將概要性地介紹如何選擇正確的策略來爲用戶定義類型重載這個操作符。 考慮如下的表達式: int x=4+2;   內建的 + 操作符有兩個類型相同的操作數,相加並返回右值 6,然後被賦值給 x。我們可以斷定內建的 + 是一個二元的,對稱的,可交換的操作符。它産生的結果的類型與其操作數類型相同。按照這個規測,當你爲某個用戶定義類型重載操作符時,也應該遵循相應內建操作符的特征。   爲用戶定義類型重載 + 操作符是很常見的編程任務。盡管 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 必須將該重載操作符聲明爲友元: class String { public: 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 對象。由此看來,在堆棧上返回結果仍然是最安全和最簡單的解決方案。 [url=/bbs/detail_1785255.html][img]http://image.wangchao.net.cn/it/1323424124074.gif[/img][/url] 更多內容請看C/C++技術專題 C/C++進階技術文檔專題,或
󰈣󰈤
王朝萬家燈火計劃
期待原創作者加盟
 
 
 
>>返回首頁<<
 
 
 
 
 熱帖排行
 
 
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有