箭頭(->)操作符是個二進制操作符,其左操作數是類對象的位址或者是重載了箭頭運算符的類對象,右操作數是類的成員。箭頭操作符重載函數隻能是類的成員函數(參考為什麼有的操作符重載函數隻能是成員函數?)。
箭頭運算符的使用方法為:
obj->mem;
obj->func();
obj為某個類對象的位址,mem和func()分别是該對象的成員變量和成員函數,這樣的用法是我們之前學習的。在引入操作符重載後,obj還可以是重載了->操作符的類對象(注意是對象而非位址),mem和func()依舊是類對象的成員,但是注意,它不再是obj對象的成員。
對于上述代碼語句,編譯器是這樣處理的:
步驟(1):倘若obj是指針(或者說位址),指向的是具有成員變量mem(成員函數func())的類對象,那麼obj->mem傳回成員變量mem,obj->func()調用成員函數func();
步驟(2):倘若obj是一個重載了->操作符的類對象,那麼調用obj對象的operator->()函數,該函數的傳回值有兩種情況:①傳回指針,執行步驟(1);②傳回重載了->操作符的類對象,執行步驟(2),直至傳回的是指針。
是以若obj是一個重載了->的類對象,那麼mem和func()将不是obj的成員,而是->運算符重載函數最終傳回的指針指向的對象的成員。
用下面代碼加深了解:
(1)左操作數是對象的指針
using namespace std;
struct A
{
void func() { printf("A::func()\n"); }
};
int main(void)
{
A *aobj = new A;
aobj->func(); //簡單,列印A::func()
return ;
}
(2)左操作數是重載->操作符的類對象,該重載函數傳回的是某個對象的指針
struct C
{
void func() { printf("C::func()\n"); }
};
struct B
{
C m_c;
C* operator->() { return &m_c; }
};
int main(void)
{
B bobj; //bobj是一個對象,但它重載了->操作符
bobj->func(); //執行的是C::func(),即列印C::func()
return ;
}
(3)左操作數是重載->操作符的類對象,重載函數傳回的是另一個重載了->操作符的類的對象
struct F
{
void func() { printf("F::func()\n"); }
};
struct E
{
F m_f;
F* operator->() { return &m_f; } //傳回m_f對象的位址
};
struct D
{
E m_e;
E operator->() { return m_e; } //傳回m_e對象,該對象重載了->操作符
};
int main(void)
{
D d;
d->func(); //等價于d.operator->().operator->()->func(),列印F::func()
return ;
}