扫二维码与项目经理沟通
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流
回调函数就是一个被作为参数传递的函数。在C语言中,回调函数只能使用函数指针实现,在C++、Python、ECMAScript等更现代的编程语言中还可以使用仿函数或匿名函数。
十年的秀山土家族苗族网站建设经验,针对设计、前端、开发、售后、文案、推广等六对一服务,响应快,48小时及时工作处理。营销型网站建设的优势是能够根据用户设备显示端的尺寸不同,自动调整秀山土家族苗族建站的显示方式,使网站能够适用不同显示终端,在浏览器中调整网站的宽度,无论在任何一种浏览器上浏览网站,都能展现优雅布局与设计,从而大程度地提升浏览体验。创新互联建站从事“秀山土家族苗族网站设计”,“秀山土家族苗族网站推广”以来,每个客户项目都认真落实执行。
回调函数的使用可以大大提升编程的效率,这使得它在现代编程中被非常多地使用。同时,有一些需求必须要使用回调函数来实现。
最著名的回调函数调用有C/C++标准库stdlib.h/cstdlib中的快速排序函数qsort和二分查找函数bsearch中都会要求的一个与strcmp类似的参数,用于设置数据的比较方法。
意义
因为可以把调用者与被调用者分开,所以调用者不关心谁是被调用者。它只需知道存在一个具有特定原型和限制条件的被调用函数。简而言之,回调函数就是允许用户把需要调用的函数的指针作为参数传递给一个函数,以便该函数在处理相似事件的时候可以灵活的使用不同的方法。
回调函数就是一个通过函数指针调用的函数。
如果把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,那就说这是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。
不管怎么说,回调函数是继承自C语言的。在C++中,应只在与C代码建立接口或与已有的回调接口打交道时,才使用回调函数。除了上述情况,在C++中应使用虚拟方法或仿函数(functor),而不是回调函数。
扩展资料
回调函数的好处:
1、回调函数可以把调用者与被调用者分开,所以调用者不关心谁是被调用者。它只需知道存在一个具有特定原型和限制条件的被调用函数。简而言之,回调函数就是允许用户把需要调用的函数的指针作为参数传递给一个函数,以便该函数在处理相似事件的时候可以灵活的使用不同的方法。
2、回调可用于通知机制。例如,有时要在A程序中设置一个计时器,每到一定时间,A程序会得到相应的通知,但通知机制的实现者对A程序一无所知。那么,就需一个具有特定原型的函数指针进行回调,通知A程序事件已经发生。实际上,API使用一个回调函数SetTimer()来通知计时器。
参考资料来源:百度百科-回调函数
我举个排序的例子
#include stdio.h
#include string.h
typedef struct person {
int age;
char name[20];
double height;
} person;
int sortOnAge(person* a, person* b) // 以年龄排序,用于回调
{
return a-age b-age;
}
int sortOnName(person* a, person* b)// 以姓名排序,用于回调
{
return strcmp(a-name, b-name);
}
int sortOnHeight(person* a, person* b)// 以身高排序,用于回调
{
return a-height b-height;
}
void sort(person* a, int n, int (*comparator)(person* a, person* b)) // 排序用函数,接受待排数组和比较用回调函数
{
int i, j;
person t;
for(i = 0; i n; ++i) {
for(j = 0; j n-i-1; ++j) // 简单冒泡排序
if(comparator(a+j, a+j+1)) { // 调用回调函数比较
memcpy(t, a+j, sizeof(t));
memcpy(a+j, a+j+1, sizeof(t));
memcpy(a+j+1, t, sizeof(t));
}
}
}
void show(const char* msg, person* p, int n) // 输出数组
{
puts(msg);
int i;
for(i = 0; i n; ++i)
printf("%d\t%s\t%.2f\n", p[i].age, p[i].name, p[i].height);
putchar('\n');
}
int main()
{
person a[] = {
15, "lex", 153.5,
14, "jack", 155.8,
13, "liu", 144.8,
16, "king", 165.3,
15, "Ben", 159.7
};
show("origin:", a, 5);
sort(a, 5, sortOnAge); show("sort on age:", a, 5); // 以年龄排序
sort(a, 5, sortOnName); show("sort on name:", a, 5); // 以姓名排序
sort(a, 5, sortOnHeight); show("sort on height:", a, 5); // 以身高排序
}
可能你已经看出来了,对于这个排序函数,如果你不用回调的话,你可以使用以下几种方式来等效
第一:写三个sort函数
缺点:代码冗余,复用性不高
第二:sort函数接受一个数字,用于定义常量判断排序的依据
比如sort(person* a, int n, int cmpmode)
...
switch(cmpmode)
case SORT_ON_AGE: { cmp = a[i].age a[i+1].age }; break;
case SORT_ON_NAME: { cmp = a[i].name a[i+1].name }; break;
.....
if(cmp){ /*交换*/ }
缺点:这个方法比方法一要好,不过仍不够灵活,而且同样造成代码冗余,缺乏复用性,有n种排序选择就要写n个cmp = a[i].xxx a[i+1].xxx
到这里你已经看出回调函数的好处了吧。特别地,使用回调函数可以在一定程度上封装调用函数的逻辑,这在写库和api的时候就很有用了,比如windows的n多api里都用到回调函数,os来调用你提供的一个函数地址,这种情况你无论如何也不可能自己去实现那个调用api吧,所以回调函数作用多多
callback Function
回调函数是应用程序提供给Windows系统DLL或其它DLL调用的函数,一般用于截获消息、获取系统信息或处理异步事件。应用程序把回调函数的地址指针告诉DLL,而DLL在适当的时候会调用该函数。回调函数必须遵守事先规定好的参数格式和传递方式,否则DLL一调用它就会引起程序或系统的崩溃。通常情况下,回调函数采用标准WindowsAPI的调用方式,即__stdcall,当然,DLL编制者可以自己定义调用方式,但客户程序也必须遵守相同的规定。在__stdcall方式下,函数的参数按从右到左的顺序压入堆栈,除了明确指明是指针或引用外,参数都按值传递,函数返回之前自己负责把参数从堆栈中弹出。
理解回调函数!
程序在调用一个函数(function)时(通常指api).相当于程序(program)呼叫(Call)了一个函数(function)关系表示如下:
call(调用)
program --------------------→ dll
程序在调用一个函数时,将自己的函数的地址作为参数传递给程序调用的函数时(那么这个自己的函数称回调函数).需要回调函数的 DLL 函数往往是一些必须重复执行某些操作的函数.关系表示如下:
call(调用)
program --------------------→ dll
↑ ¦
¦_______________________________¦
callback(回调)
当你调用的函数在传递返回值给回调函数时,你就可以利用回调函数来处理或完成一定的操作。至于如何定义自己的回调函数,跟具体使用的API函数有关,很多不同类别的回调函数有各种各样的参数,有关这些参数的描述一般在帮助中有说明回调函数的参数和返回值等.其实简单说回调函数就是你所写的函数满足一定条件后,被DLL调用!
也有这样的说法(比较容易理解):
回调函数就好像是一个中断处理函数,系统在符合你设定的条件时自动调用。为此,你需要做三件事:
1. 声明;
2. 定义;
3. 设置触发条件,就是在你的函数中把你的回调函数名称转化为地址作为一个参数,以便于DLL调用。
C语言中函数指针与普通指针没什么差别,只是指向的内容不同而已。主要作用:
1、实现面向对象编程中的多态性。
2、回调函数。
函数指针是指向函数的指针变量。 因此“函数指针”本身首先应是指针变量,只不过该指针变量指向函数。这正如用指针变量可指向整型变量、字符型、数组一样,这里是指向函数。
C在编译时,每一个函数都有一个入口地址,该入口地址就是函数指针所指向的地址。有了指向函数的指针变量后,可用该指针变量调用函数,就如同用指针变量可引用其他类型变量一样,在这些概念上是大体一致的。
函数指针有两个用途:调用函数和做函数的参数。
函数指针实质是一个指针,该指针指向函数的入口地址,回调函数只不过是通过参数自己调用自己,首先它是一个函数,跟函数指针完全没有什么可比性,风马牛不相及。
定义一个函数指针你看下:void (*func)(int ,int);
再给你看看比如:int *p; int max(int x,int y);
p=max;这里呢就是一个指针指针一个函数,所以这个p也是一个函数指针,说白了它就只是一个指针,只是不过指向的是一个函数而已,就这么简单。
就这样调用就可以了int result=(*p)(a,b)
你们不要总是把函数指针和指针函数比来比去的,也没有什么可比性,函数指针就只是一个指针,指针函数就只是一个函数就完了!
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流