2012-01-08 29 views
89

我明白大多數操作符重載,與成員訪問運營商->.*->*重載成員訪問運營商 - > *(C++)

在具體的例外,什麼被傳遞給這些操作功能。 ,什麼應該返回?

操作員功能如何(例如operator->(...))知道被引用的成員?它可以知道嗎?它甚至需要知道嗎?

最後,有沒有需要考慮的常量因素?例如,當重載像operator[]這樣的東西時,通常你需要一個const和非const的版本。成員訪問操作符是否需要const和非const版本?

+1

我相信上面的C++ - 常見問題涉及上述Q中提到的所有Q. – 2012-01-08 13:19:54

+0

'operator->'的const'和non-'const'版本不是必需的,但提供兩者都可以有用。 – 2012-01-08 13:26:22

+1

另請參閱:http://yosefk.com/c++fqa/operator.html – 2012-01-08 13:42:55

回答

102

->

這是唯一真正棘手的一個。它必須是非靜態成員函數,並且不需要參數。返回值用於執行成員查找。

如果返回值是類類型的另一個對象,而不是指針,則後續成員查找也由operator->函數處理。這被稱爲「下鑽行爲」。語言鏈接在一起調用operator->,直到最後一個返回一個指針。

struct client 
    { int a; }; 

struct proxy { 
    client *target; 
    client *operator->() const 
     { return target; } 
}; 

struct proxy2 { 
    proxy *target; 
    proxy &operator->() const 
     { return * target; } 
}; 

void f() { 
    client x = { 3 }; 
    proxy y = { & x }; 
    proxy2 z = { & y }; 

    std::cout << x.a << y->a << z->a; // print "333" 
} 

->*

這一個是隻在棘手的有什麼特別的地方。 非重載版本需要一個指向左側類類型指針的對象和右側成員類型指針對象。但是當你重載它時,你可以接受任何你喜歡的參數並返回你想要的任何東西。它甚至不必是非靜態成員。

換句話說,這只是一個普通的二元運算符,如+,-/。另請參見:Are free operator->* overloads evil?

.*.

這些不能超載。當左邊是類類型時,已經有了一個內置的含義。也許能夠將它們定義爲左側的指針會有點意義,但是語言設計委員會認爲這會比有用的更困惑。

重載->->*..*只能填寫情況下,表達式將是不確定的,它永遠不會改變,這將是沒有超載的有效表達的意思。

+2

你最後的陳述並非完全正確。例如,您可以重載'new'運算符,即使它沒有超載也是有效的。 – Matt 2013-02-17 04:49:11

+4

@Matt好吧,'new'總是被重載,或者重載規則並不適用於它(13)。5/5:分配和釋放函數,操作符new,操作符new [],操作符delete和操作符delete []在3.7.4中完整描述。除非在3.7.4中明確規定,否則這個 子條款的其餘部分中的屬性和限制不適用於它們。)但是重載一元'&'或二元'&&',''''或','或者增加'operator ='的重載,或者重載任何非泛化的枚舉類型都可以改變表達式的含義。澄清聲明,謝謝! – Potatoswatter 2013-02-18 01:05:40

8

->運算符不知道指向哪個成員,它只是提供一個對象來執行實際的成員訪問。

另外,我看不出爲什麼你不能提供const和非const版本。

5

當你重載operator - >()(沒有參數在這裏傳遞)時,編譯器實際上做的是遞歸調用 - >,直到它返回一個指向類型的實際指針。然後它使用正確的成員/方法。

這很有用,例如,創建封裝實際指針的智能指針類。重載的operator->被調用,執行任何操作(例如鎖定線程安全),返回內部指針,然後編譯器調用 - >來獲取這個內部指針。

至於常量 - 它已在評論和其他答案(您可以並且應該提供兩者)中得到回答。

+1

正是我在找的東西;謝謝! – Andrew 2017-02-18 05:22:13

20

運算符 - >是特殊的。它具有額外的非典型約束:它必須返回一個對象(或對一個對象的引用),該對象還具有一個指針解引用操作符,或者它必須返回一個可用於選擇指針解引用操作符箭頭的指針指着。「 Bruce Eckel: Thinking CPP Vol-one : operator->

提供了方便的額外的功能,所以您不必調用

a->->func(); 

你可以簡單地做:

a->func(); 

這使得運營商 - >與其他運營商不同重載。

+2

這個答案值得更多的信貸,你可以從該鏈接下載Eckel的書,信息在第一卷的第12章。 – 2014-12-29 14:36:25

20

您不能超載成員訪問.(即->所做的第二部分)。但是,您可以使一元運算符過載運算符*(即->所做的第一部分)過載。

C++ ->運算符基本上是兩個步驟的聯合,如果您認爲x->y等效於(*x).y,則這很明顯。 C++允許您在x是您的類的實例時自定義如何處理(*x)部分。

對於->重載的語義有點奇怪,因爲C++允許您返回一個常規指針(它將用於查找指向的對象)或返回另一個類的實例,如果此類還提供了->運算符。在第二種情況下,從這個新實例繼續搜索解除引用的對象。

+2

很好的解釋!我猜這對於' - > *'是相同的,因爲它相當於'(* x)。*'的形式? – Bingo 2012-01-08 23:34:50