赞
踩
C/C++有一类函数叫做回调函数,回调函数有助于实现功能的模块化。虽然C++已经有了多态来使得程序更加多元化,但是有些时候多态不能满足我们的需求,这时候使用回调函数会有意想不到的效果。废话不多说,下面来举个栗子:
假如一家公司有一个老板和两个员工,老板负责给两个员工布置任务,员工执行完成后告知老板执行的结果。很简单的例子,实现方式也很多,这里我们使用回调函数的方式来让员工通知老板任务的执行结果,下面直接上代码。
- #include <iostream>
- #include "callback_helper.h"
-
- class Staff
- {
- CB_MESSAGEREGISTER
- public:
- Staff(int n) : num (n) , result(0) {}
-
- void work()
- {
- std::cout << "Staff" << num << ": working" << std::endl;
- // ...
- result = (num%2);
- std::cout << "Staff" << num << ": finished" << std::endl;
- feedback(num, &result);
- }
-
- int result;
- int num;
- };
-
- class Boss
- {
- CB_MESSAGERECEIVER(Boss, feedbackOfStaff)
- public:
- Boss() : staff1(1), staff2(2) {
- CB_INSTALLMESSAGEHANDLER((&staff1))
- CB_INSTALLMESSAGEHANDLER((&staff2))
- }
-
- void start() {
- std::cout << "Boss: start" << std::endl;
- staff1.work();
- staff2.work();
- }
-
- int feedbackOfStaff(int staffNum, void *msg)
- {
- int *p = reinterpret_cast<int *>(msg);
- int result = 0;
- if (p)
- result = *p;
- std::cout << "Boss: Staff" << staffNum << (result?" OK":" NG") << std::endl;
-
- return 0;
- }
-
- Staff staff1;
- Staff staff2;
- };
-
- int main(int argc, char* argv[])
- {
- Boss a;
- a.start();
-
- return 0;
- }
-
这段代码中有几个宏定义: CB_MESSAGERECEIVER, CB_INSTALLMESSAGEHANDLER, CB_MESSAGEREGISTER
CB_MESSAGERECEIVER:定义一个静态的C++成员函数callbackMessageReceiver,放在主类(例子中的Boss)里面,主类的成员类变量(例子中Staff)实际回调的是这个静态函数,并传入主类的this指针;
CB_MESSAGEREGISTER: 定义一个结构体(CB_MessageHandlerVariant),用来存放主类的this指针和回调函数指针,并提供一个函数安装主类回调函数,一个函数执行主类回调函数;
CB_INSTALLMESSAGEHANDLER: 将主类的this指针和上面定义的类静态函数指针传入到成员类变量中;
定义放在了头文件callback_helper.h中,callback_helper.h的内容如下:
- #if !defined (_CALLBACK_HELPER_)
- #define _CALLBACK_HELPER_
-
- typedef int (*CB_ReceiverFunction)(void *cd, int type, void *param);
- struct CB_MessageHandlerVariant {
- CB_ReceiverFunction fc;
- void *cd; // this point
-
- CB_MessageHandlerVariant () : fc(0), cd(0) {}
- };
-
- #define CB_MESSAGERECEIVER(Class, Function) \
- static int callbackMessageReceiver(void *cd, int type, void *param) \
- { \
- Class *pthis = reinterpret_cast<Class *>(cd); \
- if (pthis) \
- return pthis->Function(type, param); \
- else \
- return 0; \
- }
-
- #define CB_INSTALLMESSAGEHANDLER(Sender) \
- Sender->registerMessageHandler(callbackMessageReceiver, reinterpret_cast<void *>(this));
-
- #define CB_MESSAGEREGISTER \
- struct CB_MessageHandlerVariant msgHandler; \
- public: \
- void registerMessageHandler(CB_ReceiverFunction pfun, void *cd) \
- {msgHandler.fc = pfun; msgHandler.cd = cd;} \
- int feedback(int type, void *param = NULL) \
- {if (msgHandler.cd && msgHandler.fc) return msgHandler.fc(msgHandler.cd, type, param); return 0;}
-
-
- #endif
执行结果如下:
- Boss: start
- Staff1: working
- Staff1: finished
- Boss: Staff1 OK
- Staff2: working
- Staff2: finished
- Boss: Staff2 NG
可能有人会说根本不需要用到回调函数的方法,主类直接读取成员类的结果不就好了,是的这个例子确实变复杂了,但是如果Staff是开进程或者其他异步的方式执行任务,并且需要在执行完成后立即通知主类,就只能用这个方式了。
就写到这里,也不知道有没有讲清楚,由于时间仓促、水平有限,代码里面当然也难免会有不足之处,欢迎大家批评指正。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。