当前位置:   article > 正文

C++类回调函数使用(利用宏定义简化使用,含例子和源码简介)

C++类回调函数使用(利用宏定义简化使用,含例子和源码简介)

C/C++有一类函数叫做回调函数,回调函数有助于实现功能的模块化。虽然C++已经有了多态来使得程序更加多元化,但是有些时候多态不能满足我们的需求,这时候使用回调函数会有意想不到的效果。废话不多说,下面来举个栗子:

假如一家公司有一个老板和两个员工,老板负责给两个员工布置任务,员工执行完成后告知老板执行的结果。很简单的例子,实现方式也很多,这里我们使用回调函数的方式来让员工通知老板任务的执行结果,下面直接上代码。

  1. #include <iostream>
  2. #include "callback_helper.h"
  3. class Staff
  4. {
  5. CB_MESSAGEREGISTER
  6. public:
  7. Staff(int n) : num (n) , result(0) {}
  8. void work()
  9. {
  10. std::cout << "Staff" << num << ": working" << std::endl;
  11. // ...
  12. result = (num%2);
  13. std::cout << "Staff" << num << ": finished" << std::endl;
  14. feedback(num, &result);
  15. }
  16. int result;
  17. int num;
  18. };
  19. class Boss
  20. {
  21. CB_MESSAGERECEIVER(Boss, feedbackOfStaff)
  22. public:
  23. Boss() : staff1(1), staff2(2) {
  24. CB_INSTALLMESSAGEHANDLER((&staff1))
  25. CB_INSTALLMESSAGEHANDLER((&staff2))
  26. }
  27. void start() {
  28. std::cout << "Boss: start" << std::endl;
  29. staff1.work();
  30. staff2.work();
  31. }
  32. int feedbackOfStaff(int staffNum, void *msg)
  33. {
  34. int *p = reinterpret_cast<int *>(msg);
  35. int result = 0;
  36. if (p)
  37. result = *p;
  38. std::cout << "Boss: Staff" << staffNum << (result?" OK":" NG") << std::endl;
  39. return 0;
  40. }
  41. Staff staff1;
  42. Staff staff2;
  43. };
  44. int main(int argc, char* argv[])
  45. {
  46. Boss a;
  47. a.start();
  48. return 0;
  49. }

这段代码中有几个宏定义: 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的内容如下:

  1. #if !defined (_CALLBACK_HELPER_)
  2. #define _CALLBACK_HELPER_
  3. typedef int (*CB_ReceiverFunction)(void *cd, int type, void *param);
  4. struct CB_MessageHandlerVariant {
  5. CB_ReceiverFunction fc;
  6. void *cd; // this point
  7. CB_MessageHandlerVariant () : fc(0), cd(0) {}
  8. };
  9. #define CB_MESSAGERECEIVER(Class, Function) \
  10. static int callbackMessageReceiver(void *cd, int type, void *param) \
  11. { \
  12. Class *pthis = reinterpret_cast<Class *>(cd); \
  13. if (pthis) \
  14. return pthis->Function(type, param); \
  15. else \
  16. return 0; \
  17. }
  18. #define CB_INSTALLMESSAGEHANDLER(Sender) \
  19. Sender->registerMessageHandler(callbackMessageReceiver, reinterpret_cast<void *>(this));
  20. #define CB_MESSAGEREGISTER \
  21. struct CB_MessageHandlerVariant msgHandler; \
  22. public: \
  23. void registerMessageHandler(CB_ReceiverFunction pfun, void *cd) \
  24. {msgHandler.fc = pfun; msgHandler.cd = cd;} \
  25. int feedback(int type, void *param = NULL) \
  26. {if (msgHandler.cd && msgHandler.fc) return msgHandler.fc(msgHandler.cd, type, param); return 0;}
  27. #endif
 

执行结果如下:

  1. Boss: start
  2. Staff1: working
  3. Staff1: finished
  4. Boss: Staff1 OK
  5. Staff2: working
  6. Staff2: finished
  7. Boss: Staff2 NG

 可能有人会说根本不需要用到回调函数的方法,主类直接读取成员类的结果不就好了,是的这个例子确实变复杂了,但是如果Staff是开进程或者其他异步的方式执行任务,并且需要在执行完成后立即通知主类,就只能用这个方式了。

就写到这里,也不知道有没有讲清楚,由于时间仓促、水平有限,代码里面当然也难免会有不足之处,欢迎大家批评指正。

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/知新_RL/article/detail/573796
推荐阅读