回调函数理解,回调函数
分类:计算机编程

“回调函数就是叁个通过函数指针调用的函数。

什么是回调函数

回调函数便是叁个经过函数指针调用的函数。倘让你把函数的指针(地址卡塔 尔(英语:State of Qatar)作为参数字传送递给另贰个函数,当以此指针被用为调用它所针没有错函数时,大家就说这是回调函数。回调函数不是由该函数的落到实处方一直调用,而是在特定的平地风波或规范发出时由此外的一方调用的,用于对该事件或规范举行响应。

  今天看到回调函数,有一点迷糊,找了累累探索引擎的素材,都不是让自身很能精通,看了《c和指针》小编才通晓了。

黄金年代经您把函数的指针(地址卡塔 尔(英语:State of Qatar)作为参数字传送递给另一个函数,当以此指针被用来调用其所针对的函数时,我们就说那是回调函数。”

举个例证

  • 函数 A
var url = "./data/employee.json";
$.getRemoteData(url, function (data) {

    console.log(data);// json 对象

});
  • 函数 b
getRemoteData: function (URL, callBack) {
    $iframe = $("<iframe style='display: none;'></iframe>");
    $iframe.prop("src", URL);
    $("body").append($iframe);
    $iframe.on('load', function () {
        // 转换成 jsonStr ,contentDocument是 iframe 节点的 DOM 方法获取 contentDocument
        var ifrDocument = this.contentDocument;
        var jsonStr = $(ifrDocument).find("body").text();
        // 利用浏览器内置的 JSON.parse() 方法转换成 json 对象
        var jsonObj = JSON.parse(jsonStr);
        // 把 json 对象传给回调函数
        callBack(jsonObj);
        // 删除 document 中的 iframe 元素
        $(this).remove();
    });

简单易行描述一下什么是回调函数:

——英特网摘来的大器晚成段回调函数的演说,好呢,比较刚毅。

此处大家从概念剖判出手

回调函数正是二个通过函数指针调用的函数。假若您把函数的指针(地址卡塔 尔(阿拉伯语:قطر‎作为参数字传送递给另二个函数,当那几个指针被用为调用它所指向的函数时,我们就说那是回调函数。

开首解释:函数 A 中的佚名函数 function(){} 把本人自己充任为二个参数,传给函数 B,在函数 B 中,callBack 便是一个履行,当callback(jsonObj);的时候调用了函数 A 中的无名氏函数。所以函数 A 中的那些无名函数就是佚名回调函数

回调函数不是由该函数的达成方平素调用,而是在一定的风云或标准发出时由其余的一方调用的,用于对该事件或条件进行响应。

浅显解释:函数 A 中的那么些佚名函数正是兑现方,是当特定事件或标准(函数 A 必要分析 json 数据)的时候,由此外一方(函数 B)调用,用于对该事件或规范(这里是内需获得远程 json 对象时)举办响应。
(完)

  客商把一个函数指针作为参数字传送递给任何函数,后面一个将“回调”客商的函数。假如函数可以再分歧的时光实行不后生可畏类型的劳作或许施行只可以由函数调用者定义的干活,都足以采纳回调函数。回调函数无法理解比较的值的品种,所以参数的花色被声称为void*。表示二个针对未知类型的指针。能够因此函数指针来促成回调函数。两个指向性回调函数的指针作为参数字传送递给另三个函数,后面一个使用那么些指针调用回调函数。

我们来打个比如:

  只怕说了太多定义也不会卓殊清楚,来多少个例证说说。

高校要开展出入拘押了,告诉门卫发掘宠物和车要上报(这些是回调函数注册卡塔 尔(英语:State of Qatar),然后管理职员依据门卫的上报进行拍卖(那么些是回调函数的试行卡塔 尔(英语:State of Qatar)。

  当大家在在链表中搜寻多个数时,大家日常会那样写:

import os,sys

Find={
    'Type':'',
    'Color':'',
    'Size':''
}#定义汇报内容

def CallFun(cmd,Find):#回调函数的定义,在这里处理各种回调情况
    if cmd=='Type':
        if Find['Type']=='Dog' or Find['Type']=='Cat':
            print 'A Pet:'
        else:
            print 'A Transport:'
    elif cmd=='Print':
        print Find
    else:
        print 'error'

def GiveInfo(i):#该段是填报信息,可忽略
    type0=['Dog','Cat']
    type1=['Car','Truck']
    color0=['Black','White','Pink']
    size0=['Big','Middle','Small']
    t0=i % 2
    if  t0== 0:
        Find['Type'] = type0[i%2]
    else:
        Find['Type'] = type1[i%2]
    Find['Color'] = color0[i%3]
    Find['Size'] = size0[i%3]

def FindObj(num,cmd,CallBackFun):#发现目标,启动回调函数
    GiveInfo(num)#门卫填报信息
    CallBackFun(cmd,Find)#启动回调函数

if __name__ == '__main__':
    cmds=['Type','Print','Try']
    for i in range(0,10):#定义十次上报
        print '----------%d-------------'%i
        FindObj(i,cmds[i%3],CallFun)#这里注册回调函数(就是告知门卫的过程)
 1 Node *search_list( Node *node, int const value ) 2 { 3     while ( NULL != node ){ 4         if ( node->value == value ){ 5             break; 6         } 7         node = node->link; 8     } 9 10     return node;11 }

回调利于模块解耦。

那样就限定我们只还好探求的数必需是int类型,当变为别的体系时大家就不能用那个函数,可是再一次写一个函数,他们再也代码又太多。那我们看看用回调函数怎么着办到。  

回调函数找出:

1 int compare_int( void const *a, void const *b )2 {3     if ( *( int * )a == *( int * )b ){4         return 0;5     }6 7     return 1;8 }

 1 Node *search_list(Node *node, void const *value,  2     int (void const *, void const *))  //函数指针 3 { 4     while(node != NULL){ 5         if(compare(&node->value, value) == 0)  //相等 6             break; 7         node = node->link; 8     } 9     return node;10 }

 这样利用回调函数就能够消除如上难点。我们把四个函数指针(int (void const *, void const *)卡塔 尔(英语:State of Qatar)作为参数字传送递给寻觅函数,查找函数将“回调”相比函数。当大家需求实行不生龙活虎类型的可比时大家创造调用该函数。举个例子:当大家整形查找时:search_list( root, &desired_value, compare_int );,使用字符查找时:search_list( root, &desired_value, compare_char );。那便是回调函数简单的行使,当然回调函数不仅只是用于这几个回顾的事例,比如库函数qsort正是选择回调函数达成。

  函数原型如下:

void qsort(   void *base,    //字符串首地址   size_t num,  //排序总个数   size_t width, //排序元素的大小   int (__cdecl *compare )(const void *, const void *)  //函数指针);

  库函数达成:

void qsort(   void *base,    //字符串首地址   size_t num,  //排序总个数   size_t width, //排序元素的大小   int (__cdecl *compare )(const void *, const void *)  //函数指针);

{    char *lo, *hi;              /* ends of sub-array currently sorting */    char *mid;                  /* points to middle of subarray */    char *loguy, *higuy;        /* traveling pointers for partition step */    size_t size;                /* size of the sub-array */    char *lostk[STKSIZ], *histk[STKSIZ];    int stkptr;                 /* stack for saving sub-array to be processed */    /* validation section */    _VALIDATE_RETURN_VOID(base != NULL || num == 0, EINVAL);    _VALIDATE_RETURN_VOID(width > 0, EINVAL);    _VALIDATE_RETURN_VOID(comp != NULL, EINVAL);    if (num < 2)        return;                 /* nothing to do */    stkptr = 0;                 /* initialize stack */    lo = (char *)base;    hi = (char *)base   width * (num-1);        /* initialize limits */    /* this entry point is for pseudo-recursion calling: setting       lo and hi and jumping to here is like recursion, but stkptr is       preserved, locals aren't, so we preserve stuff on the stack */recurse:    size =  / width   1;        /* number of el's to sort */    /* below a certain size, it is faster to use a O sorting method */    if (size <= CUTOFF) {        __SHORTSORT(lo, hi, width, comp, context);    }    else {        /* First we pick a partitioning element.  The efficiency of the           algorithm demands that we find one that is approximately the median           of the values, but also that we select one fast.  We choose the           median of the first, middle, and last elements, to avoid bad           performance in the face of already sorted data, or data that is made           up of multiple sorted runs appended together.  Testing shows that a           median-of-three algorithm provides better performance than simply           picking the middle element for the latter case. */        mid = lo   (size / 2) * width;      /* find middle element */        /* Sort the first, middle, last elements into order */        if (__COMPARE(context, lo, mid) > 0) {            swap(lo, mid, width);        }        if (__COMPARE(context, lo, hi) > 0) {            swap(lo, hi, width);        }        if (__COMPARE(context, mid, hi) > 0) {            swap(mid, hi, width);        }        /* We now wish to partition the array into three pieces, one consisting           of elements <= partition element, one of elements equal to the           partition element, and one of elements > than it.  This is done           below; comments indicate conditions established at every step. */        loguy = lo;        higuy = hi;        /* Note that higuy decreases and loguy increases on every iteration,           so loop must terminate. */        for  {            /* lo <= loguy < hi, lo < higuy <= hi,               A[i] <= A[mid] for lo <= i <= loguy,               A[i] > A[mid] for higuy <= i < hi,               A[hi] >= A[mid] */            /* The doubled loop is to avoid calling comp, since some               existing comparison funcs don't work when passed the same               value for both pointers. */            if (mid > loguy) {                do  {                    loguy  = width;                } while (loguy < mid && __COMPARE(context, loguy, mid) <= 0);            }            if (mid <= loguy) {                do  {                    loguy  = width;                } while (loguy <= hi && __COMPARE(context, loguy, mid) <= 0);            }            /* lo < loguy <= hi 1, A[i] <= A[mid] for lo <= i < loguy,               either loguy > hi or A[loguy] > A[mid] */            do  {                higuy -= width;            } while (higuy > mid && __COMPARE(context, higuy, mid) > 0);            /* lo <= higuy < hi, A[i] > A[mid] for higuy < i < hi,               either higuy == lo or A[higuy] <= A[mid] */            if (higuy < loguy)                break;            /* if loguy > hi or higuy == lo, then we would have exited, so               A[loguy] > A[mid], A[higuy] <= A[mid],               loguy <= hi, higuy > lo */            swap(loguy, higuy, width);            /* If the partition element was moved, follow it.  Only need               to check for mid == higuy, since before the swap,               A[loguy] > A[mid] implies loguy != mid. */            if (mid == higuy)                mid = loguy;            /* A[loguy] <= A[mid], A[higuy] > A[mid]; so condition at top               of loop is re-established */        }        /*     A[i] <= A[mid] for lo <= i < loguy,               A[i] > A[mid] for higuy < i < hi,               A[hi] >= A[mid]               higuy < loguy           implying:               higuy == loguy-1               or higuy == hi - 1, loguy == hi   1, A[hi] == A[mid] */        /* Find adjacent elements equal to the partition element.  The           doubled loop is to avoid calling comp, since some           existing comparison funcs don't work when passed the same value           for both pointers. */        higuy  = width;        if (mid < higuy) {            do  {                higuy -= width;            } while (higuy > mid && __COMPARE(context, higuy, mid) == 0);        }        if (mid >= higuy) {            do  {                higuy -= width;            } while (higuy > lo && __COMPARE(context, higuy, mid) == 0);        }        /* OK, now we have the following:              higuy < loguy              lo <= higuy <= hi              A[i]  <= A[mid] for lo <= i <= higuy              A[i]  == A[mid] for higuy < i < loguy              A[i]  >  A[mid] for loguy <= i < hi              A[hi] >= A[mid] */        /* We've finished the partition, now we want to sort the subarrays           [lo, higuy] and [loguy, hi].           We do the smaller one first to minimize stack usage.           We only sort arrays of length 2 or more.*/        if ( higuy - lo >= hi - loguy ) {            if (lo < higuy) {                lostk[stkptr] = lo;                histk[stkptr] = higuy;                  stkptr;            }                           /* save big recursion for later */            if (loguy < hi) {                lo = loguy;                goto recurse;           /* do small recursion */            }        }        else {            if (loguy < hi) {                lostk[stkptr] = loguy;                histk[stkptr] = hi;                  stkptr;               /* save big recursion for later */            }            if (lo < higuy) {                hi = higuy;                goto recurse;           /* do small recursion */            }        }    }    /* We have sorted the array, except for any pending sorts on the stack.       Check if there are any, and do them. */    --stkptr;    if (stkptr >= 0) {        lo = lostk[stkptr];        hi = histk[stkptr];        goto recurse;           /* pop subarray from stack */    }    else        return;                 /* all subarrays done */}

  为了越来越好地了然回调函数,接下去大家来写二个谐和的qsort函数

int char_compare(void const * c1,void const* c2) //比较函数{    int a = *((int*)c1);    int b = *((int*)c2);    return a>b ? 1 : a<b ? -1 : 0;}void Swap(char *str1,char *str2,int size) {    while (size--)    {        char tmp = *str1;        *str1 = *str2;        *str2 = tmp;        str1  ;str2  ;    }}void MyQsort(void *str,int len,int elen,int(void const*,void const*))  //基于回调函数写的排序算法{    int i = 0;    int j = 0;    int flag = 1;    for (i=0; i<len-1; i  )    {        for (j=0; j<len-1-i; j  )        {            if (compare((char*)str j*elen,(char*)str (j 1)*elen)>0)            {                flag = 0;                Swap((char*)str j*elen,(char*)str (j 1)*elen,elen);            }        }        if             return;    }}

看了例题在的话说原理

  一句话来说,回调函数正是三个通过函数指针调用的函数。若是您把函数的指针作为参数字传送递给另四个函数,当那一个指针被用为调用它所指向的函数时,大家就说那是回调函数。回调函数不是由该函数的兑现方一贯调用,而是在一定的平地风波或条件产生时由其它的一方调用的,用于对该事件或标准进行响应。

回调函数落成的体制是:

  定义一个回调函数;

  提供函数达成的一方在早先化的时候,将回调函数的函数指针注册给调用者;

  当特定的平地风波或标准发生的时候,调用者使用函数指针调用回调函数对事件张开处理。

看了多少个例证我们应该能精晓回调函数了,倘若还也是有何难题得以私信作者,提出把指针那节理解彻底,这是指针的

参谋文献:

KennethA.Reek著 徐波 译.c和指针.人民邮政和邮电通讯出版社.二零零六

 

本文由pc28.am发布于计算机编程,转载请注明出处:回调函数理解,回调函数

上一篇:条件下采用动态链接库dll的安详严整,之间的涉 下一篇:没有了
猜你喜欢
热门排行
精彩图文