2012-04-23 64 views
10

編輯:繼Mike Seymour的評論之後,我用operator char *() const;替換operator std::string() const;,並相應地更改了實現。這允許隱式轉換,但由於某些原因,無符號long int運算符優先於char *運算符,這只是感覺不正確......另外,我不想在c類,當我有std :: string。我有一個預感,我的CustomizedInt類需要從一些東西繼承,以支持我期望的功能。有沒有人請詳細說明Mike對std::basic_string的評論?我不確定我是否理解正確。C++隱式轉換運算符優先級


我有這樣一段代碼:

#include <string> 
#include <sstream> 
#include <iostream> 

class CustomizedInt 
{ 
private: 
    int data; 
public: 
    CustomizedInt() : data(123) 
    { 
    } 
    operator unsigned long int() const; 
    operator std::string() const; 
}; 

CustomizedInt::operator unsigned long int() const 
{ 
    std::cout << "Called operator unsigned long int; "; 
    unsigned long int output; 
    output = (unsigned long int)data; 
    return output; 
} 

CustomizedInt::operator std::string() const 
{ 
    std::cout << "Called operator std::string; "; 
    std::stringstream ss; 
    ss << this->data; 
    return ss.str(); 
} 

int main() 
{ 
    CustomizedInt x; 
    std::cout << x << std::endl; 
    return 0; 
} 

哪個打印 「被叫運營商unsigned long int類型; 123」。我的問題是這些:

  1. 我刪除了操作符unsigned long int後,爲什麼我需要明確地將x轉換爲std :: string?爲什麼不直接調用隱式轉換運算符(std :: string)?
  2. 是否有任何文檔解釋哪些隱式轉換被允許以及哪些是它們的優先順序?看來,如果我將運算符unsigned int與運算符unsigned long int一起添加到此類中,則會收到關於運算符<的模糊性的編譯器錯誤...另外,我知道定義這樣的運算符可能是可憐的練習,但我不確定我完全理解相關的注意事項。有人可以請他們概述一下嗎?僅僅定義公共方法ToUnsignedLongInt和ToString會更好嗎?
+0

這是相關的:[通過隱式轉換爲字符串流式傳輸對象時的重載分辨率失敗](http://stackoverflow.com/questions/6677072/overload-resolution-failure-when-streaming-object-via-implicit-conversion to-str) – 2012-04-23 18:16:51

+0

@Als:讓我們慢慢來...我還沒有準備好潛入模板:) – 2012-04-23 18:40:46

回答

8

我刪除了操作符unsigned long int後,爲什麼我需要明確地將x轉換爲std :: string?爲什麼不直接調用隱式轉換運算符(std :: string)?

<<字符串的版本是一個模板,通過std::basic_string模板的參數parametrised(std::string本身是該模板的專門化)。它只能通過依賴於參數的查找來選擇,而且只有當參數實際上是std::basic_string的特化時纔有效,而不是可轉換的。

是否有任何文檔解釋哪些隱式轉換是允許的以及哪些是它們的優先順序?

規則非常複雜,你需要閱讀C++標準的完整故事。簡單的經驗法則是,隱式轉換不能包含多個用戶定義的轉換,並且(正如您發現的那樣),隱式轉換的結果不能用於通過依賴於參數的查找來選擇模板特化。

我不知道我完全理解相關的注意事項。有人可以請他們概述一下嗎?

我也不完全瞭解它們;隱式轉換,名稱查找和模板專業化之間的相互作用(以及我現在無法想到的其他因素)相當複雜,大多數人都沒有傾向於全部學習。有不少隱式轉換不會發生的情況,以及其他發生在您不期望的情況時可能發生的情況;個人而言,我發現在大多數情況下避免隱式轉換更容易。

只是定義公共方法ToUnsignedLongInt和ToString會更好嗎?

這可能是一個好主意,以避免不必要的轉換。你可以通過讓他們解決您的問題,並在必要時明確地使用它們:

std::cout << std::string(x) << std::endl; 

在C++ 11,你可以宣佈他們explicit,所以他們只能以這種方式使用。在我看來,如果可以的話,這將是最好的選擇;否則,我會按照你的建議使用顯式的轉換函數。

順便說一下,返回類型main()必須是int,而不是void

+0

Mike:感謝您花時間提供這樣的詳細評論。它確實清楚了一些事情。另外,感謝您發現「void main」這個小問題。我應該記得使用正確的版本,不管是什麼:) – 2012-04-23 18:34:05