簡體   English   中英

運算符> =重載的奇怪行為

[英]Odd behavior with operator>= overloading

我在C ++中有一個運算符重載的奇怪行為。 我有一個課程,我需要檢查其內容是否大於或等於一個長整數。 我重載了> =運算符以進行此檢查,我的聲明如下:

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

我必須說,我的班級也有一個強制轉換為雙精度雙精度運算符,該運算符僅在特定條件下才能正常工作。 現在,當我使用該運算符時,編譯器會抱怨運算符> =的使用模棱兩可,替代方法是:

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

現在,如何強制程序使用我的運算符?

2015年更新:或者,如果您想使用(double)obj語法而不是obj.to_double()語法保持轉換能力,請在該轉換函數前添加該關鍵字作為前綴來使其explicit 您需要顯式強制轉換,然后才能觸發轉換。 就我個人而言,我更喜歡.to_double語法,除非將轉換轉換為bool因為在那種情況下,即使if if(obj)explicit ,轉換也被if(obj)使用,並且比if(obj.to_bool())更具可讀性。在我看來。


刪除轉換運算符。 它將一直引起麻煩。 具有像

to_double()

或類似的返回double值並顯式調用該函數以獲取double的函數。

對於當前的問題,存在以下問題:

obj >= 10

考慮一下這種表達。 內置運算符使用轉換運算符long double()為您的類型按用戶定義的轉換順序匹配第一個參數。 但是您的函數通過從int到long double的標准轉換序列(從整數到浮點轉換)匹配第二個參數。 當有兩個參數的轉換時,它總是模棱兩可的,但至少有一個參數可以更好地轉換,而其余的參數在一次調用中轉換得並不差。 在您的情況下,內置參數與第二個參數的匹配較好,但第一個參數較差,但是您的函數與第一個參數的匹配較好,但第二個參數較差。

這很令人困惑,因此這里有一些示例(從char到int的轉換稱為提升,這比從char到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) 更好 ,但由於您的其他參數(long double)仍未選擇您的運算符版本)需要從參數進行轉換,該轉換比內置運算符對該參數所需的轉換(完全匹配)差。

重載解析是C ++中的一件事,因此不可能記住其中的所有微妙規則。 但是,制定粗略的計划是完全可能的。 我希望它對你有所幫助。

通過有效地說明對double的隱式轉換,您可以有效地說明這一點,我的類等效於double ,因此,您不必在意是否使用了double的內置運算符> =。 如果您確實關心的話,那么您的類實際上就不等同於double並且您應該考慮不提供對double隱式轉換,而應提供顯式的 GetAsDouble或ConvertToDouble成員函數。

您目前不清楚的原因是,對於表達式t >= d ,其中t是類的實例,而d是雙精度型,編譯器總是必須提供左側或右側的轉換。如此一面手的表情確實是am昧的。 要么調用toperator double ,然后使用針對double s的內置運算符> =,要么必須將d提升為long double然后使用成員運算符> =。

編輯,您已經更新了問題,建議您將轉換為long double,並將比較與int進行比較。 在這種情況下,最后一段應為:

您目前不清楚的原因是,對於表達式t >= d ,其中t是類的實例,而dint ,編譯器始終必須提供左側或右側的轉換。如此一面手的表情確實是am昧的。 要么調用toperator long double ,然后使用內置運算符> =來表示long doubleint ,要么必須將d提升為long double並使用成員運算符> =。

我假設您正在與文字int進行比較,而不是long double int

MyClass o;

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

如果是這樣的話,兩種選擇都一樣好/復雜。

使用operator long double()

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

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

  1. 內置將int轉換為long double
  2. MyClass::operator>=(long double)

您的聲明中有long double 嘗試將其更改為double

將運算符重載與自定義強制轉換結合使用會使類的用戶非常困惑。 問問自己,此類用戶希望它自己轉換為雙精度還是與雙精度可比? .greaterThan(double)函數不會實現相同的目標,但不會令用戶感到驚訝嗎?

我猜想,在進行比較之前,您總是可以明確地將對象轉換為兩倍,以避免產生歧義。 但是,如果您是我,我將重新考慮以上方法,並專注於編寫直觀且行為毫不奇怪的代碼,而不是花哨的類型轉換和運算符重載。

(受到FQA 關於運算符重載的奇妙咆哮的啟發)

  • 內置運算符> =(long double,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; }

因此,編譯器無法確定轉換方式。 (模棱兩可。)

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

當心a> = b調用與b> = a不同的方法的情況

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM