C++类的成员函数指针

时间:2021-12-12 19:04:44

//*********************************************************
//条款一 类的成员函数指针变量之间可相互强转
//*********************************************************

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);
//可以看到这里将子类成员函数的地址赋给了基类成员函数指针类型的变量