前言
因为程序一直有用到这个回调函数,虽然能够大概看得懂,知道是把函数指针从一个类传到另一个类,给这另一个类用,但是,里面具体详细的内容不太明确。在这里,稍微记录一下。
正文
首先,我们先了解一下函数指针是啥东西?
函数指针
定义:指向存放函数空间首地址的指针变量。
解析:函数指针是指向函数的指针变量。 因此“函数指针”本身首先应是指针变量,只不过该指针变量指向函数。这正如用指针变量可指向整型变量、字符型、数组一样,这里是指向函数。如前所述,C在编译时,每一个函数都有一个入口地址,该入口地址就是函数指针所指向的地址。有了指向函数的指针变量后,可用该指针变量调用函数。
回调函数
定义:回调函数就是一个通过函数指针调用的函数。如果你把函数的指针地址作为参数传递给另一个函数,当这个指针被用来调用它所指向的函数的时候,我们就说这是回调函数。
为何要使用回调函数?
- 因为有些时候,我们调用函数的时机是:当触发某个特定的事件,这个时候调用你定义的函数。而如果采用一般的方法,你可能需要去用啥信号槽进行一定的监听,监听你所要控制的事件的时机。而用回调函数,就不存在这个问题。你只需要把函数传到对应的函数中,当这个函数执行时,它自然就会调用这个回调函数,从而执行你所需要的功能。
- 第二种解释方式:注册回调简单解释就是一个高层调用底层,底层再回过头来调用高层,这个过程就叫注册回调, 连接高层和底层就叫注册回调函数。高层程序C1调用底层程序C2,而在底层程序C2 又调用了高层程序C2的callback函数,那么这个callback函数对于高层程序C1来说就是回调函数。 在设计模式中这个方式叫回调模式。
例子
这篇文章讲了一个例子,值得探讨一下,这应该也是我能想到的回调的一个用处。
比如,我们写A B C D 四个函数,封装成一个库文件,然后我们的主函数里面要写一个功能函数,这个功能要用到函数A,假如不用函数指针,这个功能函数就要调用函数A,下次如果用到函数B,那么我们得删掉A,调用函数B,每次都要修改这个函数很麻烦,但如果使用回调函数就不一样了,我们可以定义4个函数指针,把4个函数的地址分别赋给4个函数指针,然后将函数指针当作参数传递给功能函数,功能函数就可以通过修改参数来调用对应的函数,而它本身不用做任何的修改。这样的话,功能函数就可以根据不同的情况,通过函数指针去调用不同的函数,代码如下:
#include <stdio.h>
#include <stdlib.h>
float ADD(float a, float b)
{
return a + b;
}
float SUB(float a, float b)
{
return a - b;
}
float MUL(float a, float b)
{
return a * b;
}
float DIV(float a, float b)
{
return a / b;
}
float (*A)(float x, float y) = ADD;
float (*B)(float x, float y) = SUB;
float (*C)(float x, float y) = MUL;
float (*D)(float x, float y) = DIV;
float fun(float x, float y, float(*p)(float x, float y)) {
return p(x, y);
}
int main()
{
printf("%f", fun(2, 3, A));
}
- 当使用回调函数时,你就可以利用传入函数的指针去调用在外面那个类的一些函数了。
给一个比较简单的回调处理函数
//回调处理类
class CSampleCaptureEventHandler : public ICaptureEventHandler
{
public:
void DoOnImageCaptured(CImageDataPointer& objImageDataPointer, void* pUserParam)
{
MDeviceDahengG3UC* pDev = static_cast<MDeviceDahengG3UC*>(pUserParam);
pDev->triggerEvent(objImageDataPointer);
}
};
回调对象的声明:CSampleCaptureEventHandler *m_pCaptureEventHandler;
外面的注册:m_objStreamPtr->RegisterCaptureCallback(m_pCaptureEventHandler,this);
在外面要使用的地方,你只需要注册一下,把那个要传进来的函数的指针传进来就可以了。然后,在这里进行一定的强制类型转换,就可以去调用对应的函数了。当这个指向的函数内部发生特定条件时,这个回调函数就生效了。
注册函数的作用就是告诉底层代码,使用者想让你调用的函数是那个,也就是传进去的指针对应的那个函数。
总结
希望你能耐下心来好好把这些文字看完,也许有些许理解上的偏差,但我觉得大体应该是没错的,值得你花费几分钟去看下来。
参考文献
- 注册回调函数(一)
- 使用注册回调函数
- 回调函数的作用
若有错误,请多指教~