成員函式指標(Pointer to member function)


函式指標 中曾經介紹過如何宣告一個指向函式的指標,您也可以宣告一個指標指向物件的成員函式,這邊仍然使用 建構函式、解構函式 中的SafeArray類別來作說明。

要宣告一個成員函式指標與單純的宣告函式指標是類似的,所不同的是您要指定是哪一個類別的函式,例如:
int (SafeArray::*mfPtr1)(int) = 0;
void (SafeArray::*mfPtr2)(int, int) = 0;

上例中宣告了mfPtr1與mfPtr2兩個成員函式指標,初始值設定為0,表示目前不指向任何成員函式,mfPtr1可以指向SafeArray具有 int返回值及一個int參數的成員函式(例如get()),而mfPtr2可以指向SafeArray中具有void及兩個int參數的成員函式(例如 set())。

上例中宣告成員函式指標的語法過於複雜,可以使用typedef加以簡化,例如:
typedef void (SafeArray::*MFPTR1)(int, int);   
typedef int (SafeArray::*MFPTR2)(int);

MFPTR1 mfPtr1 = 0;
MFPTR2 mfPtr2 = 0;

為了取得一個成員函式的位址值,您可以使用&取址運算子並指明是哪個類別的哪個成員函式,例如:
mfPtr1 = &SafeArray::set;
mfPtr2 = &SafeArray::get;

成員函式在記憶體中只會存在一份,在調用成員函式時,具體要配合實際的物件位址,物件位址會是 this 指標 指向的位址,所以透過物件調用成員函式的方式如下:
SafeArray safeArray(10);

// 以下與safeArray.set(2, 10) 相同

(safeArray.*mfPtr1)(2, 10);

// 以下的成員函式呼叫部份與safeArray.get(2)相同
cout << (safeArray.*mfPtr2)(2) << endl;

"." 運算子之後使用*對指標取值,括號是給定引數。如果是物件指標的話,則可以如下:
SafeArray *safePtr = &safeArray;
// 以下相當於safePtr->set(2, 100)
(safePtr->*mfPtr1)(2, 100);

下例是個簡單的運行程式,示範如何使用成員函式指標:
  • main.cpp
#include <iostream>
#include "SafeArray.h"
using namespace std;

int main() {
//int (SafeArray::*mfPtr1)(int) = 0;
//void (SafeArray::*mfPtr2)(int, int) = 0;
typedef void (SafeArray::*MFPTR1)(int, int);
typedef int (SafeArray::*MFPTR2)(int);

MFPTR1 mfPtr1 = 0;
MFPTR2 mfPtr2 = 0;

mfPtr1 = &SafeArray::set;
mfPtr2 = &SafeArray::get;

SafeArray safeArray(10);

for(int i = 0; i < safeArray.length; i++) {
(safeArray.*mfPtr1)(i, (i+1)*10);
}

for(int i = 0; i < safeArray.length; i++) {
cout << (safeArray.*mfPtr2)(i) << " ";
}
cout << endl;

SafeArray *safePtr = &safeArray;

(safePtr->*mfPtr1)(2, 100);

for(int i = 0; i < safePtr->length; i++) {
cout << (safePtr->*mfPtr2)(i) << " ";
}
cout << endl;

return 0;
}

執行結果:

10 20 30 40 50 60 70 80 90 100
10 20 100 40 50 60 70 80 90 100