做投融资平台的网站都有哪些?建设行网站修改电话
回调函数
当程序跑起来时,一般情况下,应用程序会时常通过API调用库中实现准备好的函数。但是有些库函数需要先传一个函数给它,好在合适时调用。传入且被调用的函数叫做回调函数。
基础知识
所谓回调,就是模块A要通过模块B的某个函数b()完成一定功能,但是函数b无法完成所有的功能,需要反过来调用模块A中的某个函数a()来完成,这个a()就是回调函数
-
约定接口规范
在模块B必须约定接口规范,也就是定义回调函数a()的函数原型
这里回调函数原型的定义最好遵循
typedef void(*SCT_XXX)(LPVOID Ip,const CBParamStruct& cbNode);
- SCT_XXX是指向函数的指针类型(原文说是回调函数的名称)
- IP是回调上下文
- CBParamStruct是回调参数,一般由于要回调的参数不止一个,所以定义一个结构体更加方便
-
回调函数的注册
为了让模块B知道自己将要用的回调函数,必须有一个函数或者语句进行注册回调函数
注册回调函数的定义遵循
void RFC_XXX(SCT_XXX pnf,LPVOID Ip);
- RFC_XXX是注册函数名
- pfn是SCT_XXX类型的指针变量指向回调函数
- Ip是回调上下文
- 一般在A模块初始化完B模块后调用,将A模块中定义的回调函数地址赋值给pfn,Ip赋值为this
-
在A模块中要进行的事情
首先将回调函数声明成静态的
static void CF_XXX(LPVOID Ip,const CBParamStruct& cbNode);
函数的参数必须与B模块中回调函数原型参数保持一致
回调函数的实现
void basketball()//函数1
{printf("选择篮球");
}
void football()//函数2
{printf("选择足球");
}
void selectball(void (* ball)())//函数3
{printf("选择什么球?");ball();
}
int main(void)
{selectball(basketball);selectball(football);return 0;
}
函数1和2都属于模块A,函数3属于模块B,主函数在调用模块B中的函数时,模块B得不到答案,故传递指针给函数3 ,得到正确答案
进阶回调
C语言回调实例
//callbackText.c
//1.定义函数onHeight(回调函数)
//@onHeight 函数名
//@height 参数
//@context 上下文
void onHeight(double height,void* context)
{sprint("current height is %lf",height);
}
//2.定义onHeight函数的原型
//@CallbackFun 指向函数的指针类型
//@height 回调参数,当有多个参数时,可以定义一个结构体
//@context 回调上下文,在c中一般传入nullptr,在c++中可以传入对象指针
typedef void (*CallbackFun)(double height,void* context);
//3.定义注册回调函数
//@registHeightCallback 注册函数名
//@callback 回调函数原型
//@context 回调上下文
void registHeightCallback(CallbackFun callback,void* context)
{double h=100;callback(h,nullptr);
}
//4.main函数
void main()
{registHeightCallback(onHeight,nullptr);
}
很多时候,注册的时候并不调用回调函数,而是在其他函数中调用,那我们可以定义一个CallbackFun全局指针变量,在注册的时候将函数指针赋给它,在调用的时候调用它
//定义全局指针变量
CallbackFun* m_pCallback;
//定义注册回调函数
void registHeightCallback(CallbackFun callback,void* context)
{m_pCallback = callback;
}
//定义调用函数
void printHeightFun(double height)
{m_pCallback(height,nullptr);
}
C++回调函数
C++回调函数扩展自C,与C略有不同的是,C++可以使用全局函数和静态函数作为回调函数。考虑到全局函数会破坏封装性,所以一般都用静态成员函数。故除了理解函数指针,还要理解静态成员函数,具体一点是在静态函数成员中访问非静态成员函数的方法,因为我们很可能需要获取静态成员函数中的数据。
使用场景描述:使用他人提供的SDK,如:
//CallbackFun类型
//@CallbackFun 指向函数的指针类型
//@height 回调参数,当有多个参数时,可以定义一个结构体
//@contex 回调上下文,在C中一般传入nullptr,在C++中可传入对象指针
typedef void (*CallbackFun)(double height, void* contex);//注册回调函数接口
//@registHeightCallback 注册函数名
//@callback 回调函数原型
//@contex 回调上下文
void registHeightCallback(CallbackFun callback, void* contex)
首先定义一个静态成员函数并注册
//sensorTest.cpp
//接收数据类class Sensor
class Sensor{
public:Sensor(){}~Sensor(){}//定义回调函数onHeightstatic void onHeight(double height, void* contex){cout << "current height is " << height << endl;}//定义注册回调函数void registCallback(){registHeightCallback(onHeight, this);}
};//main 函数
void main()
{Sensor sens;sens.registCallback();
}
静态成员函数访问非静态成员函数的方法
在静态成员函数中只能出现静态变量和静态函数的,但是有些时候需要访问非静态成员函数或者变量
//接收数据类class Sensor
class Sensor{
public:Sensor(){}~Sensor(){}//定义回调函数onHeightstatic void onHeight(double height,void* context){//cout << "current height is "<< height << endl;Sensor* sen = (Sensor*)context;if(sen)//判断sen是否有效sen->getHeight(height);}//定义注册回调函数void registCallback(){registHeightCallback(ontHeight,this);}//新增成员函数void getHeight(double height){cout << "current height is "<< height <<endl;}
};