一、概念
回调函数就是一个通过函数指针调用的函数。
如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。
回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。
二、机制
⑴、定义一个回调函数;
⑵、提供函数实现的一方在初始化的时候,将回调函数的函数指针注册给调用者;
⑶、当特定的事件或条件发生的时候,调用者使用函数指针调用回调函数对事件进行处理。
三、意义
因为可以把调用者与被调用者分开,所以调用者不关心谁是被调用者。它只需知道存在一个具有特定原型和限制条件的被调用函数。简而言之,回调函数就是允许用户把需要调用的函数的指针作为参数传递给一个函数,以便该函数在处理相似事件的时候可以灵活的使用不同的方法。
四、调用约定
回调函数原型中可以找到__stdcall,因为它以双下划线打头,所以它是一个特定于编译器的扩展,说到底也就是微软的实现。
任何支持开发基于Win32的程序都必须支持这个扩展或其等价物。以__stdcall标识的函数使用了标准调用约定,为什么叫标准约定呢,因为所有的Win32 API(除了个别接受可变参数的除外)都使用它。
标准调用约定的函数在它们返回到调用者之前,都会从堆栈中移除掉参数,这也是Pascal的标准约定。
但在C/C++中,调用约定是调用者负责清理堆栈,而不是被调用函数;为强制函数使用C/C++调用约定,可使用__cdecl。另外,可变参数函数也使用C/C++调用约定。
四、案例
//定义回调函数原型
typedef __stdcall void(*pFunc)(vector<string>&);
//定义回调函数
void printfMsg(vector<string> &vecString)
{
for(int i = 0; i<vecString.size();i++)
{
printf(“[%s]\n”,vecString[i].c_str());
}
}
//类如下
class CMyClass
{
public:
~CMyClass(void);
CMyClass(void);
void SetCallbackFunc(pFunc func)
{
m_func = func;
}
void work()
{
vector<string> vecString;
vecString.push_back("a");
vecString.push_back("b");
(*m_func)(vecString);
}
private:
pFunc m_func;
}
//使用
CMyClass myClass;
//将回调函数的函数指针注册给调用者
myClass.SetCallbackFunc(&printfMsg);
myClass.work();