簡體   English   中英

解決運算符[]的模糊重載

[英]Resolving ambiguous overload of operator[]

我有這門課:

class MyClass {

    public:

        int operator[](const std::string&);
        const std::string& operator[](const int&) const;

    ...
};

但是,如果我調用第二個運算符w / const literal 0,它的工作量很大:

MyClass myclass;
std::cout << myclass[0] << std::endl;

我收到了這個錯誤:

In function 'int main()':
ambiguous overload for 'operator[]' in 'myclass[0]'
note: candidates are:
note: const int MyClass::operator[](const string&)|
note: const string& MyClass::operator[](const int&) const

我想我明白了什么情況(0可以是字符串或int?),但我的問題是:有沒有辦法解決這個問題並保持運算符重載?

調用MyClass::operator[](const std::string&)涉及轉換:

MyClass&MyClass& myclass MyClass& :完美匹配

0intconst char*std::string :用戶定義的轉換

調用MyClass::operator[](const int&) const涉及轉換:

來自MyClass& myclass MyClass& const MyClass& :const qualified

0intint :完美匹配

在這種情況下,當一個重載對於參數X“更好”但是對於參數Y不同的重載是“更好”時,過載都不能被認為是最好的重載,並且編譯器必須抱怨(假設沒有第三次重載超過兩者) 。

是否可以將兩個重載更改為const或兩個non-const 如果沒有,您可以添加第三個重載來處理這種情況:

const std::string& operator[](int n) {
    return static_cast<const MyClass&>(*this)[n];
}

0不能是一個string ,但它可以是一個指針,這意味着它可以隱式轉換string 請注意,對於其他常量積分(例如142 ,情況並非如此 - 僅為0

4.10指針轉換

1 /空指針常量是整數類型的整數常量表達式(5.19)rvalue,其計算結果為零。 空指針常量可以轉換為指針類型; 結果是該類型的空指針值,並且可以與指向對象的指針或指向函數類型的指針的每個其他值區分開來。 相同類型的兩個空指針值應相等。 將空指針常量轉換為指向cv限定類型的指針是單個轉換,而不是指針轉換的序列,后跟限定轉換(4.4)。

因此,在myclass[0]的情況下, 0可以是int ,也可以是`null指針常量。

標准還規定std::string有一個非explicit構造函數,它接受一個char指針:

size_type find_last_not_of (const charT* s, size_type pos = npos) const;

現在,由於您的operator&方法都采用const引用類型的參數,因此可以傳遞臨時值。 這就是編譯器混淆的原因 - 它不知道你想要哪一個 - 采用int那個,或者采用通過string(const char*)構造的臨時string那個string(const char*)

至於如何解決這個問題,我會后退一步。 在我看來,你的兩個operator[]函數做了截然不同的事情。 或者也許他們做同樣的事情,給出不同的輸入。 如果他們做了不同的事情,那么我會提供具有不同(適當)名稱的成員函數,並跳過嘗試使用operator[]語法。 也許其中一個方法會返回一些真正被索引的東西 - 在這種情況下,我會使用operator[]語法來表示那個,但只有那個。

如果他們確實做了同樣的事情,並且那件事是按索引返回一個項目,那么我只為它提供一個方法,並且按值獲取size_t 然后,您還可以提供某種轉換功能(最好是以免費的非成員函數的形式),從string轉換為size_t 這樣做,你可以在按string索引時編寫這樣的代碼:

myPos[str_to_index(str)];

字面值0是特殊的。 除了是八進制常量之外,它還可以轉換為任何指針類型的空指針。 這使得0對於std::stringchar const * -constructor可行。

兩個都不是更好的原因是因為運算符的int重載具有const實例CV限定符。 這樣,兩個重載都需要轉換,同樣糟糕。

顯而易見的解決方法是明確要求const重載:

static_cast<MyClass const &>(myclass)[0]

暫無
暫無

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

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