回调函数机制:
(1)定义一个回调函数
(2)提供函数实现的一方在初始化的时候,将回调函数的函数指针注册给调用者
(3)当特定事件或条件发生的时候,调用者使用函数指针调用回调函数对事件进行处理
简单来说,回调函数就是调用者通过函数指针调用的函数,也就是说把函数指针作为参数传递给另一个函数,并用来调用它指向的函数时,这个以此函数指针为参数的函数就称为回调函数。
举个例子
#include <iostream>
#include <cstring>
using namespace std;
typedef void (*FP)(char* s); //以char*为参数的函数指针类型为FP
//三种不同函数
void f1(char* s){ cout << "f1方法: " << s << endl; }
void f2(char* s){ cout << "f2方法: " << s << endl; }
void f3(char* s){ cout << "f3方法: " << s << endl; }
class CallBack
{
public:
char* s;
CallBack(){ s = nullptr; }
CallBack(char* tmp)
{
int len = strlen(tmp) + 1;
s = new char[len];
strcpy_s(s, len, tmp);
}
void CallF(FP fp) //回调函数,调用FP类型的指针
{
fp(s);
}
~CallBack()
{
if (s != nullptr)
delete s;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
CallBack obj("hello");
//模拟事件
obj.CallF(f1);
obj.CallF(f2);
obj.CallF(f3);
return 0;
}
可以看出,回调函数不关心谁是调用者,只关心被调用函数是什么。
现在回顾回调函数的概念主要是由于看到win32程序里窗口函数都被设计成了Callback函数,因为很多时候操作系统也要调用你的窗口函数,所以窗口函数设计为callback形式开放一个接口给操作系统调用。
用上面一段代码CallF能调用一堆FP类型的函数,有时候需要根据调用者类型来安排被调用函数。
而在win32程序里消息映射里则是类似这样的一个机制
struct MSGMAP_ENTRY
{
UINT nMessage;
LONG (*pfn)(HWND, UINT, WPARAM, LPARAM);
};//消息与处理例程的对照表格
struct MSGMAP_ENTRY _messageEntries[] =
{
WM_CREATE, OnCreate,
WM_PAINT, OnPaint,
WM_SIZE, OnSize,
WM_COMMAND, OnCommand.
WM_CLOSE, OnClose,
WM_DESTROY, OnDestroy
};
#define dim(x) (sizeof(x) / sizeof(x[0]))
//于是窗口函数可以这么设计
LRESULT CALLBACK WndProc(HWND hWnd, UINT message,
WPARAM wParam, LPARAM lParam)
{
for (int i = 0; i < dim(_messageEntris); i++)
{
if (message == _messageEntries[i].nMessage)
{
return ((*_messageEntries[i].pfn)(hWnd, message, wParam, lParam));
}
}
}
当系统接收到相应消息时,可以通过nMessage来判断fpn,也就是要调用的函数,并执行它,这就是回调函数了。
就像最初那段代码我可以定义为char* s为某类型字符串时时调用f1函数,另一类型字符串时调用f2函数,等等。
其实也就是设计模式中的策略模式