轉自點擊打開鏈接
指針是指向一些內存地址的變量,既可以是數據的地址也可以是函數的地址。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似乎多餘。正如前面所講的,當它被逆向引用時,語法也需 要成員指針總是和一個對象綁定在一起。 -- 滿紙荒唐言,一把心酸淚。 都雲作者癡,誰解其中味。
stackOverflow上:點擊打開鏈接
I hope this example will clear things for you
//we have a class
struct X
{
void f() {}
void g() {}
};
typedef void (X::*pointer)();
//ok, let's take a pointer and assign f to it.
pointer somePointer = &X::f;
//now I want to call somePointer. But for that, I need an object
X x;
//now I call the member function on x like this
(x.*somePointer)(); //will call x.f()
//now, suppose x is not an object but a pointer to object
X* px = new X;
//I want to call the memfun pointer on px. I use ->*
(px ->* somePointer)(); //will call px->f();
Now, you can't use x.somePointer()
, or px->somePointer()
because there is no such member in class X. For that the special member function pointer call syntax is used... just try a few examples yourself ,you'll get used to it