入门客AI创业平台(我带你入门,你带我飞行)
博文笔记

浅谈回调函数——以sort中的cmp为例

创建时间:2016-01-11 投稿人: 浏览次数:1139

最近在看一些源码,碰到一个概念:回调函数。

虽然之前就接触过,但还是对它存在一些疑惑。所以查找了一些资料,结合学到的知识,在这里我做一个简单的介绍,希望能够帮助初学者明白“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

声明:该文观点仅代表作者本人,入门客AI创业平台信息发布平台仅提供信息存储空间服务,如有疑问请联系rumenke@qq.com。