回调函数总结

1.基础知识
  所谓回调,就是模块A要通过模块B的某个函数b()完成一定的功能,但是函数b()自己无法实现全部功能,需要反过头来调用模块A中的某个函数a()来完成,这个a()就是回调函数
 
2.使用回调函数步骤
 1).约定接口规范。
  在模块B必须约定接口规范,也就是定义回调函数a()的函数原型
这里回调函数原型的定义最好遵循 
typedef void (*SCT_XXX)(LPVOID lp, const CBParamStruct& cbNode);
SCT_XXX是回调函数名称,lp是回调上下文,CBParamStruct是回调参数,一般由于要回调的参数不止一个,所以定义一个结构体比较方便。
 2).回调函数的注册。
  为了让模块B知道自己将要使用的回调函数,必须有一个函数或语句来注册回调函数
注册回调函数的定义遵循
void RCF_XXX(SCT_XXX pfn, LPVOID lp);
RCF_XXX是注册函数名,pfn是回调函数名称(是指针),lp是回调上下文。一般在A模块初始化完B模块后调用,将A模块中定义的回调函数地址赋值给pfn,lp赋值为this。
 3).在模块A中要做的事情:
  首先将回调函数声明成静态的,
static void CF_XXX(LPVOID lp, const CBParamStruct& cbNode); 函数的参数必须与B模块中回调函数原型的参数保持一致。
  初始化B模块时,调用注册函数将模块A中声明的回调函数CF_XXX的地址传给pfn,即pfn=CF_XXX;(函数名称CF_XXX其实是个指针,指向回调函数的地址) 。
3.举例
网络编程。 在网络编程中,为了体现模块化,一般把通讯和数据处理划分开来,即通讯模块负责协议定义、数据收发,而数据处理模块只负责对收发的数据进行解析和打包,假如通讯模块开启了一个线程在持续地接收数据,这个时候问题来了,它通过什么手段把数据交到数据处理模块手中呢?每次收到数据,拿到数据处理模块的指针完成相关操作,这样有犯了两个类指针互相指的错误,也破坏了两个模块的独立性。使用回调函数这些问题都迎刃而解了,下面给出部分伪代码:

通讯模块
// 回调函数原型定义
typedef void (*DataReceiveCBFunc)(ReceiveParam & recvParam);  

// 开始接收,数据处理模块调用,相对于注册回调函数
static BOOL StartReceive(DataReceiveCBFunc pfnData, LPVOID lpContext,……);
// 接收数据的线程,一收到数据就通知回调
static UINT TH_Receive(LPVOID lp);


数据处理模块
// 开始接收数据,开启监听线程,调用上面的StartReceive函数
int StartReceiveInfo(int nListenPort, std::string strLocalIP);
// 数据接收回调函数,被CUdpEx::TH_Receive()回调
static void RecvInfoCallback(ReceiveParam &recvParam);  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值