2015年更新(由FQA的精彩rant about operator overloading啓發):或者,如果你想使用(double)obj
語法而不是obj.to_double()
語法,以保持轉化能力,通過與該關鍵字前綴使其轉換功能explicit
。你需要一個明確的演員,然後轉換爲觸發器。我個人更喜歡.to_double
語法,除非轉換是bool
,因爲在那種情況下,轉換被if(obj)
使用,即使它是explicit
,並且在我看來這比if(obj.to_bool())
更可讀。
刪除轉換運算符。它會一直造成麻煩。有一個功能,如
to_double()
或類似的,返回double值並顯式調用該函數來獲得一個double。
對於手邊的問題,存在這樣的問題:
obj >= 10
考慮到表達。內建運算符使用轉換運算符long double()通過用戶定義的類型的轉換序列來匹配第一個參數。但是你的函數通過從int到long double的標準轉換序列(積分到浮點轉換)匹配第二個參數。當有兩個參數的轉換時,它總是含糊不清的,但至少有一個參數可以更好地轉換,而其餘參數在一次調用時不會轉換得更糟。在你的情況下,內建的一個更好地匹配第二個參數,但第一個更糟糕,但你的函數更好地匹配第一個參數,但第二個參數更糟。
這是混亂的,所以這裏有一些例子(從字符爲int被稱爲促銷活動,這比轉換更好地焦炭比int之外的東西,這就是所謂轉換轉換):
void f(int, int);
void f(long, long);
f('a', 'a');
電話第一個版本。因爲第一個參數可以更好地轉換。同樣,以下依然會稱第一個:
void f(int, long);
void f(long, long);
f('a', 'a');
因爲第一個可以轉換得更好,第二個轉換不會更糟。但是以下曖昧:
void f(char, long);
void f(int, char);
f('a', 'a'); // ambiguous
它更有趣在這種情況下。第一個版本通過完全匹配接受第一個參數。第二個版本通過完全匹配接受第二個參數。但是兩個版本都至少同樣不接受他們的其他論點。第一個版本需要爲其第二個參數進行轉換,而第二個版本需要對其參數進行升級。因此,即使促銷優於轉化,對第二個版本的調用也會失敗。
這與您的情況非常相似。儘管標準轉換序列(從int/float/double轉換爲long double)比用戶定義的轉換序列(從MyClass轉換爲long double)的更好,但未選擇您的運算符版本,因爲您的其他參數(長雙)需要從比內建運營商需要的參數更糟的參數(完美匹配)轉換。
重載解析在C++中是一件複雜的事情,所以人們可以不可能記住所有細微的規則。但獲得粗略的計劃是完全可能的。我希望它能幫助你。
對不起,我的意思是長雙倍無處不在。 – tunnuz 2009-02-15 09:05:02