2012-05-05 39 views
7

據說箭頭運算符是遞歸應用的。但是,當我嘗試執行下面的代碼,它打印亂碼時,它應該打印4.運算符的遞歸應用程序 - >

class dummy 
{ 
public: 
    int *p; 

    int operator->() 
    { 
     return 4; 
    } 
}; 

class screen 
{ 
public: 
    dummy *p; 

    screen(dummy *pp): p(pp){} 
    dummy* operator->() 
    { 
     return p; 
    } 
}; 

int main() 
{ 
    dummy *d = new dummy; 
    screen s(d); 
    cout<<s->p; 
    delete d; 
} 
+6

它在哪裏說它是「遞歸應用」? –

+0

不,我不同意你的例子的工作如預期的那樣, - > opertor本質上只是一個函數調用,爲什麼它應該鑽取?如果它這樣做,你將如何控制在什麼級別停止解引用,它會使繼承和多態性更加複雜,比它已經是 – EdChum

+2

C++入門,第四版 通過Stanley B. Lippman, 第14.6 最後一段。 – user1232138

回答

10

士丹利的意思是「遞歸」僅僅是運營商應用到每一個返回的對象直到的返回的類型是一個指針。

第一次嘗試時發生在這裏:screen::operator ->返回一個指針。因此這是對編譯器嘗試的operator ->的最後一次調用。然後通過在返回的指針類型(dummy)中查找具有該名稱的成員來解決操作員的右手問題(p)。

從本質上講,只要編譯器發現語法aᵢ->b在代碼中,它基本上適用於下面的算法:

  1. 是指針類型的aᵢ?如果是這樣,請解析*aᵢ的成員b並致電(*aᵢ).b
  2. 否則,嘗試解決aᵢ::operator ->
    1. 成功時,設置aᵢ₊₁ = aᵢ::operator ->()。轉到1.
    2. 失敗時發出編譯錯誤。

我是捉襟見肘拿出一個短的,有意義的例子,其中一個operator ->鏈調用甚至是有道理的。可能唯一真正的用途是當你寫一個智能指針類。

但是,下面的玩具例子至少編譯併產生一個數字。但我不會建議實際編寫這樣的代碼。它打破封裝並使小貓哭泣。

#include <iostream> 

struct size { 
    int width; 
    int height; 
    size() : width(640), height(480) { } 
}; 

struct metrics { 
    size s; 
    size const* operator ->() const { 
     return &s; 
    } 
}; 

struct screen { 
    metrics m; 
    metrics operator ->() const { 
     return m; 
    } 
}; 

int main() { 
    screen s; 
    std::cout << s->width << "\n"; 
} 
+0

也許我的概念會更清晰,如果你能告訴我怎樣才能在這個例子中打印出4 ... – user1232138

+0

@ user1232138你不能。 'operator - >'**鏈中的最後一個調用必須返回一個指針。 –

+0

@ user1232138但是,請參閱我的更新以瞭解工作示例。請注意,我之前所說的仍然存在。你必須返回一個指針 - 所以如果你想檢索一個整數值,它需要存儲在操作符的右邊表達式中(在這裏是'size :: width')。 –

0

這筆交易一旦screen::operator->()返回一個指針(dummy*)遞歸停止,因爲內置(默認)->在該指針使用。如果你想遞歸你應該從screen::operator->()

1

C++入門(第5版)返回dummydummy&制定其570頁如下:

箭頭運營商從來沒有失去的成員訪問它的基本含義。當我們重載箭頭時,我們改變箭頭提取指定成員的對象。我們無法改變箭頭提取成員的事實。