中文版 過載箭頭運算子的理解

YunShell發表於2013-11-29
    在看到C++primer page445,過載箭頭操作符時候,發現有點疑惑。在網上一查,原來是中文版本的錯誤。搞了我半天費解。現在自己整理理解後,寫於此,後來人可以借鑑。
箭頭運算子的過載小結:
    對於該箭頭運算子,其內建型別的意義為:結構體或者類型別解引用取其成員的操作符。也就說著這玩意目的就是 取結構體或者類型別物件成員的。那麼過載一個比較重要的原則就是儘量儲存其內建型別常規的意義。正如C++Primer所說的,儘量不要去過載+號去完成-的功能。下面舉個例子。例子是從別人那裡看到的。這裡例子比較好說明問題:

#include <iostream>
using namespace std;
class A
{
public:
	void hello(){
		cout<<"A say hello "<<endl;
	}
};
class B
{
	A a;
public:
	A* operator->(){
		return &a;
	}
	void hello(){
		cout<<"B said hello"<<endl;
	}
};
class C
{
	B b;
public:
//	B* operator->(){
//		return &b;
//  	}
	B operator->(){
		return b;
	}
	void hello(){
		cout<<"C said hello"<<endl;
	}
};
void main()
{	
	C *pc;
	pc->hello(); //pc為一個類的指標 所以直接
	C c;
	c->hello();
}

所以過載箭頭運算的規則就變得簡單了。如例子中的p->hello。將按照以下順序:
1. 編譯器首先檢查是否為 預設內建->的意義.也就說是不是常規意思,p是否為類型別指標,hello是否為其所指的成員。如果是的話直接呼叫就OK了。如上述程式碼中C *pc; pc肯定為指向一個類型別的具有hello成員的指標。所以直接呼叫。所以 顯示的 c said hello. 
2.如果不是的話,就按照物件過載來考慮了。
     再檢查是不是 具有過載->運算子的物件,不是就出錯了,是的話就使用。然後就直接呼叫過載運算子了。因為運算子的過載其本質就是 函式的 過載。所以 在例子中的 C c;這裡是c是個物件。所以 呼叫 c->hello() 
就相當於呼叫 Operator->函式了。再使用其結果。既然是當做函式呼叫使用,那麼結果就是函式值了。這裡對於過載->的返回值有要求(不是類型別指標,就是類型別物件)。然後根據函式返回值。再次按照規則遞迴呼叫->。
    比如這裡: c->hello();由於c為具有hello方法的類物件。所以直接呼叫過載方法 
那麼相當於 c.operator->() ->hello() ,這裡紅色部分就是個函式,呼叫完畢,返回值。在上例中返回的是物件b.所以
其結果就相當於 b->Hello().此時 b又是個物件,並非指向類型別的指標。所以在此呼叫b的過載operataor->()方法。這裡也就是遞迴呼叫的意思。也就是b.operator->()->hello()。這裡返回是指向物件a的指標。呼叫完畢後也就相當於
a->hello()。現在 a就是一個指向一個類型別的指標,且Hello()仍然為其成員。所以這裡按照內建型別的->呼叫。也就是常規呼叫。所以輸出 "A say hello"。
     也就是:能解釋為內建型別的先解釋為內建型別的->意思。不然就查是不是過載。還要要注意對過載函式返回型別的要求。然後就是不斷重複這個解釋過程(遞迴解釋)。尤拉...


相關文章