2011-02-04 172 views
17

這裏是我的代碼示例:超載運營商 - >

class X 
{ 
public: 
     void f() {} 
}; 

class Y : public X 
{ 
public: 
     X& operator->() { return *this; } 
     void f() {} 
}; 

int main() 
{ 
     Y t; 
     t.operator->().f(); // OK 
     t->f(); // error C2819: type 'X' does not have an overloaded member 'operator ->' 
       // error C2232: '->Y::f' : left operand has 'class' type, use '.' 
} 

爲什麼編譯器正試圖從Y「移動的責任」爲操作符 - >以X?當我實現X :: op->然後我不能返回X那裏 - 編譯錯誤說「無限遞歸」,同時從X :: op->返回一些Z,再次表示Z沒有operator->,因此變得更高並且層次更高。

任何人都可以解釋這個有趣的行爲嗎? :)

回答

18

的問題是,operator ->應該返回一個指針,不是參考。這個想法是,operator ->應該返回一個指針,指向應該將指針應用於它的真實對象。例如,對於有超載operator ->類,代碼

myClass->myValue; 

轉化爲

(myClass.operator->())->myValue; 

與您的代碼的問題是,operator ->返回一個參考,所以寫

myClass.operator->().f(); 

是完全合法的,因爲你明確地調用了操作員,但是寫作

myClass->f(); 

是非法的,因爲編譯器試圖將它擴大到

myClass.operator->()->f(); 

operator->返回類型不是指針。

要解決此問題,請更改您的代碼,以便返回operator ->中的指針。如果你想超載一個操作員返回一個參考,超載operator *;指針解引用確實應該產生引用。

+9

我不會說這是假設返回一個指針,只是不管它返回需要支持`操作符 - >`。 – GManNickG 2011-02-04 09:20:24

2

的語法是錯誤的,應該是:

T-> T2

T2* T::operator ->();​ 

看看維基百科的文章:Operators in C and C++

如果你想重載,則必須使用超載運算符的正確語法

19

因爲這就是超載結束->在C++中起作用。

當您使用超載->時,表達式a->b被翻譯爲a.operator->()->b。這意味着您的重載運營商->必須返回一些本身支持運營商->的其他應用程序的內容。由於這個原因,重載的單個調用->可能會變成一個超載調用的長鏈,直到它最終到達內置的->的應用程序,這會終止鏈。

在你的情況下,你需要從你的超載->而不是X&返回。

1

你可能想:

class Y : public X 
{ 
public: 
     X* operator->() { return this; } 
     void f() {} 
};