开发中简单回调函数实例模板
1.什么是回调函数?
照顾到部分同学可能跟我之前一样,对回调函数概念还不是很明确,还请容许我在这解释一遍。熟练的可以直接跳到进阶实例 。
先来个简单的解释:回调函数就是一个通过函数指针调用的函数。如果你把一个函数的地址作为参数赋值给一个函数指针,当这个指针被用来调用其所指向的函数时,称之为回调函数。
//简单的代码说明
/*
假设存在需求:A进程中需要B进程通过A的方法通知其某一件事是否完成!!
*/
// 类型重定义方便后面书写
typedef void (*cb)(int i);
//B进程负责通知,则B进程定义“函数指针”
class B{
public:
//设置回调函数的方法
void setcallback(cb p)
{
//回调函数的精髓:将实际需要调用方法设置到函数指针中
//务必理解:这个赋值语句执行后,pCb指向传值进来的函数
this->pCb = p;
}
public:
cb pCb;//这只是个指针,是个“壳”
};
//A进程提供通知方法/函数(B进程通过此方法通知A进程)
class A{
public:
//真正执行的函数,B用此方法通知A。
void func(int i)
{
cout<<"我完成了事件:"<<i<<endl;
}
};
//使用:在A的进程/线程中:
A pA = new A;
B pB = new B;
pB->setcallback(pA->func);//约等于A告诉B:你做好了就通过这个方法告诉我
//使用:在B进程中,B完成某事之后
pB->pCb(5)//相当于===>>>pA->func(5);
至此,相信大家对回调函数应该有个小小的认识了。回调最根本的思想无非就是:其他进程(或模块)通过本进程(或模块)实现的(回调)函数,来通知本进程(模块)某些消息。不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。其中,设置回调函数(setcallback)这个动作一般称之为注册。
2.巧妙实例(本文主讲)
话不多说直接上代码
class B{
public:
//声明回调函数类
//专门用于被派生类重载的纯虚函数,嵌套类纯虚函数不会影响实例化
class CallBack{
public:
virtual void onCallBackB(int i) = 0;
}
void setCallBack(CallBack *p){
this->pCb = p;
}
public:
CallBack pCb;
};
class A: public B::CallBack{
public:
//重载B::onCallBackB方法
void onCallBackB(int i){
cout<<"方法是A实现的,事件是:"<<i<<endl;
}
A(){
oB = new B;
//注册回调
//形参是CallBack类,实参是A类,你品,你细品!
oB->setCallBack(this);
}
B *oB;
//析构我就不啰嗦了......
};
int main()
{
A* oA = new A;
//模拟B中其他事件发生需要通知到A外部调用
//想象是直接调用oB->pCb(5);
oA ->oB->pCb(5);
return 0;
}
3.小小总结一下
将可能需要通知到其他进程(模块)写进Callback嵌套类中,并修饰为纯虚函数,添加CallBack类函数指针。派生类通过继承父类中的Callback(注意这里不是直接继承B类),对父类CallBack进行重载,在调用父类的注册接口将this指针注册进父类(观察该接口的形参与实参形式,不难发现这里体现了多态,就是CallBack中声明为纯虚函数的原因)。而且当派生类需要多个模块的回调通知时,同时继承多个嵌套类的callback并不会互相冲突!