2009-02-15 118 views
2

我有一個奇怪的行爲,運算符在C++中重載。我有一堂課,我需要檢查它的內容是否大於或等於長整倍數。我重載> =運算符,使這個檢查,我的聲明如下:奇怪的行爲與運算符> =超載

bool MyClass::operator>=(long double value) const; 

我不得不說,我也有一個鑄造到長雙運營商我的課,如果沒有異常只能在某些條件下。 現在,當我使用這個操作符,編譯器會抱怨說有一個模糊的使用操作符> =和替代品:

  • 礦。
  • 內置operator>=(long double, int)

現在,我該如何強制程序使用我的操作員?

回答

3

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++中是一件複雜的事情,所以人們可以不可能記住所有細微的規則。但獲得粗略的計劃是完全可能的。我希望它能幫助你。

0

你在聲明中有long double。嘗試將其更改爲double

+0

對不起,我的意思是長雙倍無處不在。 – tunnuz 2009-02-15 09:05:02

0

您將運算符重載與自定義投射結合使用可能會讓您的課堂用戶非常困惑。問問自己,這類的用戶會期望它將自己轉換成雙倍,還是可以與雙倍?不會有.greaterThan(double)函數實現相同的目標,但不會讓用戶感到意外?

我想你可以在比較之前總是明確地把你的對象加倍,以避免含糊不清。但是如果我是你,我會重新考慮上面的方法,並專注於編寫直觀的代碼,並且以不令人吃驚的方式行事,而不是花哨的類型轉換和運算符重載。

3

通過提供隱式轉換爲double你實際上說明,我的課相當於double基於這個原因,你真的不應該介意內置的運算符> =爲double使用秒。如果您護理,那麼你的類真的不是「相當於」到double,你應該考慮的不是提供轉換爲double,而是提供了一個明確的 GetAsDouble,或ConvertToDouble成員函數。

你目前有歧義的原因是,對於一個表達式t >= d其中t是類和d的一個實例是雙,編譯器總是必須提供要麼左邊或的轉換右邊的表達方式真的很模糊。要麼調用toperator double,要麼使用內置運算符> = for double,要麼d必須提升爲long double,並且使用您的成員運算符> =。

編輯,你已經更新了你的問題,建議你的轉換是長雙倍的,而你的比較是針對整數。在這種情況下,最後一段應改爲:

你目前有歧義的原因是,對於一個表達式t >= d其中t是類和d的一個實例是int,編譯器總是必須提供左邊或右邊的轉換,所以表達式確實是不明確的。 toperator long double被調用,並且內置運算符> =用於long doubleint,或者d必須提升爲long double,並且使用您的成員運算符> =。

1

我假設你對比較文字int,而不是long double

MyClass o; 

if (o >= 42) 
{ 
    // ... 
} 

如果是這兩種選擇都一樣好/複雜的情況。

使用您的operator long double()

  1. MyClass::operator long double()
  2. 內置operator>=(long double, int)

使用您的MyClass::operator>=(long double)

  1. 內置轉換intlong double
  2. MyClass::operator>=(long double)
+0

我實際上是比較長雙。 – tunnuz 2009-02-15 09:15:29

0
  • 內置的運算符> =(長雙,INT)。

看起來你已經定義:

bool class::operator>=(long double value) { return value >= classValue; } 

而且你缺少:

bool class::operator>=(double value)  { return value >= classValue; } 
bool class::operator>=(int value)   { return value >= classValue; } 

因此,編譯器不能決定要轉換的方式。 (這是模棱兩可的。)

也許模板化的函數(或方法)會有幫助嗎?

當心情況下一個> = B調用比b > =一個不同的方法。