C 過載箭頭操作符的理解

2021-06-21 01:44:10 字數 3150 閱讀 4439

gdc注:今天在看《c++ primer》第14.6小結 「成員訪問操作符」時,對於過載箭頭操作符不是很理解,主要是對於過載該操作符後的返回值應該是乙個指標還是乙個物件。然後在網上找到了該篇文章。該篇文章首先對書中的相關知識做了乙個小結,然後設計了乙個例子。通過看這個例子,我終於明白了返回指標和返回物件之間的區別。即:

「 如果返回型別是指標,則內建箭頭操作符可用於該指標,編譯器對該指標解引用並從結果物件獲取指定成員。如果被指向的型別沒有定義那個成員,則編譯器產生乙個錯誤。

如果返回型別是類型別的其他物件(或是這種物件的引用),則將遞迴應用該操作符。編譯器檢查返回物件所屬型別是否具有成員箭頭,如果有,就應用那個操作符;否則,編譯器產生乙個錯誤。這個過程繼續下去,直到返回乙個指向帶有指定成員的的物件的指標,或者返回某些其他值,在後一種情況下,**出錯。 」

今天看《c++ primer》的成員訪問操作符。看過載箭頭操作符部分,剛開始有點迷茫,看了兩遍總算有點理解,把心得寫在這,與各位分享,如果有錯誤歡迎指正。

箭頭操作符(->)的通常用法是,使用乙個類物件的指標來呼叫該指標所指物件的成員。左運算元為物件指標,右運算元為該物件的成員。定義過載箭頭操作符之後看起來就有點特別,可以用類物件的指標來呼叫,也可以用類物件直接呼叫。

過載箭頭操作符,首先過載箭頭操作符必須定義為類成員函式。

箭頭操作符可能看起來是二元操作符:接受乙個物件和乙個成員名,對物件解引用以獲取成員。其實箭頭操作符是一元操作符,沒有顯示形參(而且是類成員,唯一隱式形參是this)。->的右運算元不是表示式,而是對應類成員的乙個識別符號,由編譯器處理獲取成員工作(編譯器對過載箭頭操作符所做的事情,比其它過載操作符要多,這裡也正是複雜的地方)。

下面這一段是《c++ primer》過載箭頭操作符的內容。

----------------------------------------華麗分割線----------------------------------------

過載箭頭操作符

箭頭操作符與眾不同。它可能表現得像二元操作符一樣:接受乙個物件和乙個成員名。對物件解引用以獲取成員。不管外表如何,箭頭操作符不接受顯式形參。

這裡沒有第二個形參,因為 -> 的右運算元不是表示式,相反,是對應著類成員的乙個識別符號。沒有明顯可行的途徑將乙個識別符號作為形參傳遞給函式,相反,由編譯器處理獲取成員的工作。

當這樣編寫時:

point->action();

由於優先順序規則,它實際等價於編寫:

(point->action)();

換句話說,我們想要呼叫的是對 point->action 求值的結果。編譯器這樣對該**進行求值:

1.如果 point 是乙個指標,指向具有名為 action 的成員的類物件,則編譯器將**編譯為呼叫該物件的 action 成員。

2.否則,如果 point(注:中文版誤寫為action) 是定義了 operator-> 操作符的類的乙個物件,則 point->action 與 point.operator->()->action 相同。即,執行 point 的 operator->(),然後使用該結果重複這三步。

3.否則,**出錯。

對過載箭頭的返回值的約束

過載箭頭操作符必須返回指向類型別的指標,或者返回定義了自己的箭頭操作符的類型別物件。

如果返回型別是指標,則內建箭頭操作符可用於該指標,編譯器對該指標解引用並從結果物件獲取指定成員。如果被指向的型別沒有定義那個成員,則編譯器產生乙個錯誤。

如果返回型別是類型別的其他物件(或是這種物件的引用),則將遞迴應用該操作符。編譯器檢查返回物件所屬型別是否具有成員箭頭,如果有,就應用那個操作符;否則,編譯器產生乙個錯誤。這個過程繼續下去,直到返回乙個指向帶有指定成員的的物件的指標,或者返回某些其他值,在後一種情況下,**出錯。

----------------------------------------華麗分割線----------------------------------------

如果上面分割線之間的內容看懂了,下面的也就不用看了哈。

根據理解,定義了3個類,c包含b,b包含a。a、b、c都定義了乙個action的成員函式。b和c都過載箭頭操作符,不同的是b的過載箭頭操作符返回的是a類物件的指標,而c的過載箭頭操作符返回的是b類物件。

[cpp]view plain

copy

#include 

using

namespace

std;  

class

a  };  

class

b  void

action()  

};  

class

c  void

action()  

};  

intmain(

intargc, 

char

*argv)    

上面**輸出結果是:

action in class c!

action in class a!

其中的**

c* pc = new c;

pc->action();

輸出的結果是

action in class c!

這個結果比較好理解,pc是類物件指標,此時的箭頭操作符使用的是內建含義,對pc解引用然後呼叫物件的成員函式action。

而下面的**

c c;

c->action();

輸出的結果是

action in class a!

其實c->action();的含義與c.operator->().operator->()->action();相同。

c是物件,c後面的箭頭操作符使用的是過載箭頭操作符,即呼叫類c的operator->()成員函式。此時返回的是類b的物件,所以呼叫類b的operator->()成員函式,b的operator->()返回的是指標,所以現在可以使用內建箭頭操作符了。對b的operator->()返回的指標進行解引用,然後呼叫解引用後的物件的成員函式action,此時呼叫的就是類a的action()。這裡存在乙個遞迴呼叫operator->()的過程,最後再使用一次內建含義的箭頭操作符。

C 過載箭頭操作符的理解

箭頭操作符 的通常用法是,使用乙個類物件的指標來呼叫該指標所指物件的成員。左運算元為物件指標,右運算元為該物件的成員。定義過載箭頭操作符之後看起來就有點特別,可以用類物件的指標來呼叫,也可以用類物件直接呼叫。過載箭頭操作符,首先過載箭頭操作符必須定義為類成員函式。箭頭操作符可能看起來是二元操作符 接...

C 過載箭頭操作符的理解

出處 今天看 c primer 的成員訪問操作符。看過載箭頭操作符部分,剛開始有點迷茫,看了兩遍總算有點理解,把心得寫在這,與各位分享,如果有錯誤歡迎指正。箭頭操作符 的通常用法是,使用乙個類物件的指標來呼叫該指標所指物件的成員。左運算元為物件指標,右運算元為該物件的成員。定義過載箭頭操作符之後看起...

C 操作符過載

1.作為成員過載 class myclass public myclass operator const myclass d cons friend myclass operator const myclass a1,const myclass a2 關於返回值型別的討論 呼叫者堆疊裡返回乙個物件效...