浅谈回调函数——以sort中的cmp为例
最近在看一些源码,碰到一个概念:回调函数。
虽然之前就接触过,但还是对它存在一些疑惑。所以查找了一些资料,结合学到的知识,在这里我做一个简单的介绍,希望能够帮助初学者明白“callback函数”究竟是什么。
一个常见的例子
也许你还不知道,自己已经用过回调函数了。
下面这段代码想必大家都很熟悉:
#include<iostream>
#include<algorithm>
using namespace std;
bool cmp(const int& a, const int& b)
{
return a>b;
}
int main()
{
int nums[10] = {4,5,3,2,3,4,6,8,9,10};
sort(nums, nums+10, cmp);
for (int i = 0; i < 10; i++)
cout<<nums[i]<<" ";
cout<<endl;
return 0;
}
上面代码将数组从大到小进行排列了。
那么sort是怎么知道如何排列的呢?这就要靠cmp了。
如果我们想从小到大排列,只需要修改cmp即可。
实际上,cmp就是一个回调函数!
(下面我们查看qsort而不是sort是因为C++的sort中第三个参数实际上是一个类对象,而cmp回调函数是该对象的成员函数,为便于理解我们直接查看qsort)。
回调函数就是函数指针的一种用法,这一点可以看以下qsort的原型,fcmp为回调函数:
void qsort(void *base,int nelem,int width,int (*fcmp)(const void *,const void *));
更一般的描述
调用函数有两种方法:
1.直接调用:在函数A的函数体里通过书写函数B的【函数名】来调用之,使内存中对应函数B的代码得以执行。这里,A称为“主叫函数”(Caller),B称为“被叫函数”(Callee)。
2.间接调用:在函数A的函数体里并不出现函数B的函数名,而是使用指向函数B的【函数指针】p来使内存中属于函数B的代码片断得以执行。
间接调用看起来比较麻烦,但是从刚刚的例子就可以看到它的优点了。
被间接调用的函数就是【回调函数】本身。
而在使用回调函数之前,首先我们需要注册回调函数,即将回调函数的地址赋给指针p。
总结:
声明函数指针p;
给函数指针p赋值,使之指向回调函数B;
把p作为参数传给函数A;
函数A通过指针p调用函数B ;
函数B的函数体得以执行。
为何叫“Callback”?
明白了上面的知识之后,可能你仍然不明白什么是回调函数——因为它的名字很令人困惑。
模块1有事找模块2(比如让模块2执行函数A),但是模块2正在忙,于是模块1留下了函数A的地址给模块2(给p指针赋值),模块2在适当的时机通过p指针调用函数A,相当于给了模块1一个回应。
更通俗的说法: 1发了条短信告诉2:A 的电话号码是XXX,你打个电话找他谈下;于是2在适当的时候根据1所给的号码给A“回”了个电话。
这里的“回调”是站在模块1的角度来看的,因为它想让B做的事得到了响应。
回调函数可以是各种各样的,比如从小到大排序,从大到小排,按照奇偶排等等,唯一的要求是,它们需要遵循一定的格式。
例子我们的例子中,cmp函数应该是如下格式:
int cmp(const void *,const void *)
THE END
- 上一篇:没有了
- 下一篇: C++类的成员函数存储方式(是否属于类的对象)