指標是指向一些記憶體位址的變數,既可以是資料的地址也可以是函數的地址。C++的
成員指標遵從同樣的原則。困難的是所有的指標需要一個地址,但在類內部沒有地
址;選擇一個類的成員意味著在類中位移。只有把這個位移和具體對象的開始地址
結合,才能得到實際地址。成員指標的文法要求選擇一個對象的同時逆向引用成員
指標。
struct simple { int a ; }
simple so;
simple* sp = &so;
如果有一個這個結構的指標sp和對象so,如果有一個指標指向一個類對象成員,甚至
假設它代表對象內一定的位移,將會發生什嗎?為了取得指標指向的內容,必須用*號逆
向引用。但是,它只是一個對象內的位移,所以還必須要指定那個對象。因此,*號要和
逆向引用的對象結合。
sp->*pm = 47; so.*pm = 47;
定義pm的文法是什嗎?其實它像任何一個指標,必須說出它指向什麼類型。並且,在定
義中也要使用一個‘*’號。唯一的區別只是必須說出這個成員指標使用什麼類的對象。
當然,這是用類名和全域操作符實現的:
定義成員指標:
int simple::*pm;
定義並初始化成員指標:
int simple::*pm = &simple::a;
因為引用到一個類而非那個類的對象,因而,&simple::a僅可作為成員指標的文法表示
。
指向函數的指標定義像下面的形式:int(*fp)(float); (*fp)的圓括弧用來迫使編譯器
正確判斷定義。沒有圓括弧,這個運算式就是一個返回int*值的函數。為了定義和使用
一個成員函數的指標,圓括弧扮演同樣重要的角色。假設在一個結構內有一個函數:
struct simple2 { int f(float); };
通過給普通函數插入類名和全域操作符就可以定義一個指向成員函數的指標:
int(simple2::*fp)(float);
初始化:
int(simple2::*fp)(float) = &simple2::f;
&號是可選的;可以用不帶參數表的函數標識符來表示地址:fp = simple2::f;
使用:
simple2 s2;
int i = (s2.*fp)(1.5);
另一個使用例子
class CB
{
int f1(){ return 1; }
int f2(){ return 2; }
int (CB::*fptr[2])();
public:
CB() { fptr[0] = CB::f1; fptr[1] = &CB::f2; }
int sel(int i){ return (this->*fptr[i])(); }
};
在建構函式中,成員指標的初始化似乎被過分地指定了。是否可以這樣寫:
fptr[1] = f2; 因為名字f2在成員函數中出現,是否可以自動地認為在這個類範圍內呢
?問題是這不符合成員函數的文法,文法要求編譯器能夠判斷將要進行什麼。當成員函
數被逆向引用時,它仍被過分地指定了,this似乎多餘。正如前面所講的,當它被逆向
引用時,文法也需要成員指標總是和一個對象綁定在一起。