在C中写回调函数非常方便,C++中定义回调函数要麻烦一些,成员函数牵涉到一个this指针问题。C++中的static成员函数没有this指针,也可以直接作为回调函数使用。C++的成员函数地址是唯一确定的,数据变量地址是可变的,因此编译器使用this指针把这两个部分连接起来,我们调用c++的成员函数,编译器会添加一个this指针到参数中。
有一个类CTest
class CTest
{
public:
void DoMsgFunc1(char* pMsg,int nID)
{
}void RegiestMsg(int nSrcID,DoMessageFunc pFunc)
{
m_pFunc = pFunc;
}void HandleMessage(int nMsgID, char* pMsg, int nID)
{
(this->*m_pFunc)(pMsg,nID);
}private:
DoMessageFunc m_pFunc;
};
定义CTest中的一个回调函数原型:
typedef void (CTest::*DoMessageFunc)(char* pMsg,int nID);
这样在类中就可以直接使用了。
注册回调函数时候,使用如下例子
CTest obj;
obj.RegiestMsg(13,&CTest::DoMsgFunc1);
如果CTest有很多派生类,如
class CTest1 : public CTest
则CTest1注册回调函数的时候,需要强制转换一下,如下
CTest1 obj1;
obj1.RegiestMsg(11,(DoMessageFunc)&CTest1::DoMsgFunc2);
MFC中的消息映射也是同样的道理,能够进行消息映射的类都是从CCmdTarget派生下来的,看看ON_COMMAND宏定义的实现就明白了。
#define ON_COMMAND(id, memberFxn) /
{ WM_COMMAND, CN_COMMAND, (WORD)id, (WORD)id, AfxSigCmd_v, /
static_cast AFX_PMSG (memberFxn) },
其中AFX_PMSG的定义如下:
typedef void (AFX_MSG_CALL CCmdTarget::*AFX_PMSG)(void)