許多開發者在嘗試將類成員函數指標傳遞給普通函數指標時,遇到編譯錯誤:Cannot convert parameter 2 from 'long (unsigned long)' to 'long (__cdecl *)(unsigned long)'。根本原因在於:非靜態成員函數擁有隱含的 this 指標,呼叫約定與普通函數不同。C++ 為此引入三個專用運算子:::*、.*、->*,構成「成員指標」體系,支援指向成員函數與成員變數。
class CTest {
public:
BOOL Init();
long OLESendTC(DWORD dwInfo);
};
// 宣告指向 CTest 成員函數的指標,參數為 DWORD,回傳 long
long (CTest::*lpFunc)(DWORD dwInfo) = &CTest::OLESendTC;
int main() {
CTest test;
(test.*lpFunc)(0); // 透過物件呼叫
CTest* pTest = &test;
(pTest->*lpFunc)(0); // 透過物件指標呼叫
return 0;
}
::* 用於宣告與取址(&CTest::OLESendTC);.* 用於物件實例呼叫;->* 用於物件指標呼叫。
成員指標常用於實作回呼機制或策略模式:
class CKernel {
long (CKernel::*lpFunc)(DWORD); // 成員函數指標
long OLESendTC(DWORD dwInfo);
public:
BOOL Init() {
lpFunc = &CKernel::OLESendTC; // 執行期繫結
return TRUE;
}
long Execute(DWORD dw) {
return (this->*lpFunc)(dw); // 呼叫綁定的成員函數
}
};
此法避免了虛函數表開銷,亦能在編譯期進行型別檢查,確保型別安全。
this 調整資訊,大小通常大於普通函數指標(單一繼承 4/8 位元組,多重/虛擬繼承更大)。this,可隱含轉換為普通函數指標。typedef 簡化宣告:typedef long (CTest::*MemFuncPtr)(DWORD);掌握成員指標機制,能讓 C++ 程式在保持型別安全的前提下,靈活實現動態派發與回呼架構。