您的位置:首页 > 编程语言

什么是回调函数Callback----自己的一点理解

2016-08-03 14:45 375 查看
何为回调函数:若把函数的指针作为函数参数传递给一个函数,当这个指着被用来调用它所指向的函数时,我们将该指针所指向的函数称为回调函数。回调函数与普通函数最大区别在于函数的调用。对普通函数而言,函数实现者可以直接拿来用,可以直接将它放在main函数内部,也可以放在别的函数内部,从而实现对它的调用。而对于回调函数而言,编程人员编写这个函数的目的仅仅是将它的指针作为参数传递给别的函数,让别的函数调用它,而不是直接使用它。

使用回调函数的一个优点就是实现了调用者与被调用者分离,调用者不必关心被调用者具体如何实现,它只要明确自己的需求即可,这个需求是由被调用者来满足的,至于具体怎么去满足,就是编程人员的事了。这样便提供了一个更加灵活的编程方法。例如,需要写一个通用的排序函数,要求能对各种类型的数据进行排序。排序的过程中必然要将两个数据进行比较。刚才说到这是一个通用的排序函数,如何实现对任何类型的数据都能比较他们之间的大小?在这个函数内部按照数据的类型分别进行比较?这显然不合适。这时候就可以使用回调函数。在这个排序函数的行参中安排一个回调函数,让这个回调函数来负责比较两个数据的大小,并且返回比较的结果。讲到这,应该能明白排序函数是这个例子中的调用者。调用者提出了自己的需求:它需要一个回调函数,帮它比较两个数据的大小,并且将比较结果传出来给它用。它并不关心比较的数据是什么类型的数据,也不关心回调函数要怎么实现,只负责提出自己的需求。编程人员接下来要做的,就是根据排序函数的需求去实现这个回调函数了。其实,调用者提出需求的同时,也提出了一个接口,编程人员要做的是按照这个接口将回调函数补充完整。这个例子从宏观来看就是:当编程人员调用这个排序函数的时候,排序函数又会调用编程人员写的另一个函数。编程人员调用的函数回过来调用编程人员自己编写的函数,这就是回调。

总结一下回调函数的一些特点:

1.调用者负责提出具体的需求。回调函数负责满足调用者的需求。

2.回调函数必须符合一定规范,这个规范由调用者的需求决定。编程人员根据规范来实现回调函数。

3.回调函数总是将自己的指针传递给调用者,好让自己被调用。

下面是回调函数的一个具体例子:

代码来源:http://www.linuxdiyf.com/viewarticle.php?id=108389

$ vi callback1.c
#include

int mycb(int a)
{
printf("parameter = %d\n", a);
return(0);
}

int callbackfn(int (*func)(int), int data)
{
func(data);
return(0);
}

int main(void)
{
callbackfn(mycb, 111);

return(0);
}


编译运行结果如下:

$ gcc callback1.c -o callback1
$ ./callback1
parameter = 111


上面这个例程中,int callbackfn(int (*func)(int), int data)是调用者,形参列表中有一个函数指针,意味着callbackfn需要一个回调函数。且这个回调函数返回值是int ,有一个形参,形参类型也是int(这里就知道了回调函数需要满足的规范了)。int mycb(int a)便是回调函数了,它是由编程人员按照规范实现的。在main函数中,mycb函数指针传给callbackfn

实现了自己的被调用。

下面是linux源码中找到一个回调函数的例子:

typedef int (*acpiphp_callback)(struct acpiphp_slot *slot, void *data);


/**
* acpiphp_for_each_slot - call function for each slot
* @fn: callback function
* @data: context to be passed to callback function
*/
static int acpiphp_for_each_slot(acpiphp_callback fn, void *data)
{
struct list_head *node;
struct acpiphp_bridge *bridge;
struct acpiphp_slot *slot;
int retval = 0;

list_for_each (node, &bridge_list) {
bridge = (struct acpiphp_bridge *)node;
for (slot = bridge->slots; slot; slot = slot->next) {
retval = fn(slot, data);
if (!retval)
goto err_exit;
}
}

err_exit:
return retval;
}


这个例子中,先定义了

typedef int (*acpiphp_callback)(struct acpiphp_slot *slot, void *data);

acpiphp_for_each_slot函数中形参列表有函数指针fn,意味着需要一个回调函数。这个fn是要编程人员参照typedef int (*acpiphp_callback)(struct acpiphp_slot *slot, void *data);去实现的。

#

转载请注明出处:

地址:http://blog.csdn.net/andoubi/article/details/52103479

作者:Andoubi
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  编程 回调函数