//*********************************************************
//條款一 類的成員函數指針變量之間可相互強轉
//*********************************************************
class A {}; class B {}; class C {}; typedef void (A::*AFun)(void); typedef int (B::*BFun)(int, int); typedef void (C::*CFun)(double); AFun pafun; BFun pbfun; CFun pcfun; //A,B,C類之間沒有任何關系,雖然以下轉換都是OK的,但基本上是沒有任何意義的 pafun = (AFun)pbfun; //OK pafun = (AFun)pcfun; //OK pbfun = (BFun)pafun; //OK pbfun = (BFun)pcfun; //OK pcfun = (CFun)pafun; //OK pcfun = (CFun)pbfun; //OK
//*********************************************************
//條款二 類的成員函數指針的使用
//*********************************************************
//A類與B類的定義 class A { public: void Test() { cout << "A::Test()" << endl; } }; class B : public A { public: void Test() { cout << "B::Test()" << endl; } }; //定義類的成員函數指針 typedef void (A::*A_mFun)(void); typedef void (B::*B_mFun)(void); //Code A a; B b; A_mFun pAFun = &(A::Test); //Note:Test成員函數必須為public,否則會報錯 B_mFun pBFun = &(B::Test); //Note:Test成員函數必須為public,否則會報錯 (a.*pAFun)(); //輸出A::Test() (b.*pBFun)(); //輸出B::Test()
(b.*pAFun)(); //輸出A::Test()
A* pA = &a; B* pB = &b; (pA->*pAFun)(); //輸出A::Test() (pB->*pBFun)(); //輸出B::Test() (pB->*pAFun)(); //輸出A::Test(),B*變量可賦值給A*變量
//******Error******
(pA->*pBFun)(); //Error: cannot convert from 'A *' to 'B *'
//Error: cannot dereference a 'B_mFun' on a 'A *'
//*****************
//******OK******
B* pB_new = (B*)pA; //強轉但本質上是有缺失的
(pB_new->*pBFun)(); //輸出B::Test(),雖OK但切記勿這樣使用,此處僅當實驗演示
//本質上類的成員函數就是帶this指針的函數,但在使用時編譯器上會增加一些限制,
//比如類的成員函數指針不能和一般的變量指針及一般的函數指針變量之間互相強轉等,這在前面隨筆中有提到
//**************
//以下才是真正有意義的,在MFC的框架機制中運用較多 //用基類變量指針+基類成員函數指針調用子類的函數 A_mFun pAFun_B = (A_mFun)&(B::Test); A* pA_B = &b; (pA_B->*pAFun_B)(); //輸出B::Test() //例如: //對話框的消息映射有: ON_BN_CLICKED(IDC_BTN_NEW_DLG, &CTestDlg::OnBnClickedBtnNewDlg) //將ID為IDC_BTN_NEW_DLG的按鈕的響應事件映射為CTestDlg的成員函數OnBnClickedBtnNewDlg //我們現在來詳細研究下ON_BN_CLICKED #define ON_BN_CLICKED(id, memberFxn) \ ON_CONTROL(BN_CLICKED, id, memberFxn) #define ON_CONTROL(wNotifyCode, id, memberFxn) \ { WM_COMMAND, (WORD)wNotifyCode, (WORD)id, (WORD)id, AfxSigCmd_v, \ (static_cast< AFX_PMSG > (memberFxn)) }, typedef void (AFX_MSG_CALL CCmdTarget::*AFX_PMSG)(void); //可以看到這里將子類成員函數的地址賦給了基類成員函數指針類型的變量