c++中回调函数(函数指针)


一、回调函数(函数指针)

1.1 函数指针

函数指针指向的是函数而非对象。和其他指针一样,函数指针指向某种特定类型。函数的类型由它的返回类型和形参类型共同决定,与函数名无关。下面,我们来定义一个函数指针

//定义了一个返回类型为bool,形参列表如下所示的函数指针p_func,指向为空
bool p_func(int a, int b) = nullptr;

1.2 回调函数的理解

C++ Primer里面举了个例子就是排序算法。为了使排序算法适应不同类型的数据,并且能够按各种要求进行排序,机智的人类把排序算法做成了一个模版(在标准模版库STL里),并且把判断两个数据之间的“大小”(也可以是“字节数”,或者其他某种可以比较的属性)这个任务(即函数)当成一个参数放在排序算法这个函数的参数列表里,而把它的具体实现就交给了使用排序算法的人。这个判断大小的函数就是一个回调函数。比如我们要给某个vector容器里面的单词进行排序,我们就可以声明一个排序算法(说人话就是,容器你随便选,比较的元素你也可以随便弄,自己写的类这些都可以比较,但是你需要自定义元素的比较方法,传入到这个排序算法中来):

void stable_sort(vector<string>::iterator iterBegin, vector<string>::iterator iterEnd, 
bool (*isShorter)(const string &, const string &))

看过c++ Primer的童鞋们应该在第十章容器的泛型算法课后习题中写过很多次这个isShorter函数了。不知道当时大家有没有想过为什么把isShorter函数传入stable_sort()函数时,是直接将isShorter函数名称传入,没有加形参?
因为在stable_sort函数中,我们是把isShorter函数的地址传入,如果加上isShorter后面加上括号,那含义将会差别巨大!

1.3 回调函数的应用价值

  1. 想象一种系统实现:在一个下载系统中有一个文件下载模块和一个下载文件当前进度显示模块,系统要求实时的显示文件的下载进度,想想很简单在面向对象的世界里无非是实现两个类而已。但是问题恰恰出在这里,显示模块如何驱动下载进度条?显示模块不知道也不应该知道下载模块所知道的文件下载进度(面向对象设计的封装性,模块间要解耦,模块内要内聚),文件下载进度是只有下载模块才知道的事情,解决方案很简单给下载模块传递一个函数指针作为回调函数驱动显示模块的显示进度。
  2. 此外,回调函数在嵌入式系统的应用也十分的广泛。究其原因,是因为我们使用的嵌入式的系统,一般会把一些函数预先写入到Flash中(类似于PC的BIOS),如果我们直接去调用这些函数,由于访问权限(这里我就不太清楚了)什么的原因,是没办法直接访问的,因此需要使用函数指针的方式将这些预先写好刷入到Flash的函数以参数的形式传入到其他函数中去。

总结

什么是回调函数,回调函数怎么定义使用以及为什么要使用回调函数,相信大家经过我的叙述,已经有了一些的了解。说到底,回调函数的产生,是因为的c++的面向对象的设计模式,既要求各模块之间要有独立性,但是也需要模块之间能够有一些联系(高内聚,低耦合)。回调函数就是作为面向对象中各个模块联系的桥梁之一。

如有不足之处,还望各位多多指教

参考文章:
【1】回调函数的实质——斗趣
【2】为什么要使用回调函数——转载第16楼

猜你喜欢

转载自blog.csdn.net/qq_42518941/article/details/111998136