什么是回调函数

作者&投稿:明邓 (若有异议请与网页底部的电邮联系)
什么是回调函数?~

回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。

回调函数

程序员常常需要实现回调。本文将讨论函数指针的基本原则并说明如何使用函数指针实现回调。注意这里针对的是普通的函数,不包括完全依赖于不同语法和语义规则的类成员函数(类成员指针将在另文中讨论)。

声明函数指针

回调函数是一个程序员不能显式调用的函数;通过将回调函数的地址传给调用者从而实现调用。要实现回调,必须首先定义函数指针。尽管定义的语法有点不可思议,但如果你熟悉函数声明的一般方法,便会发现函数指针的声明与函数声明非常类似。请看下面的例子:

void f();// 函数原型

上面的语句声明了一个函数,没有输入参数并返回void。那么函数指针的声明方法如下:

void (*) ();

让我们来分析一下,左边圆括弧中的星号是函数指针声明的关键。另外两个元素是函数的返回类型(void)和由边圆括弧中的入口参数(本例中参数是空)。注意本例中还没有创建指针变量-只是声明了变量类型。目前可以用这个变量类型来创建类型定义名及用sizeof表达式获得函数指针的大小:

// 获得函数指针的大小
unsigned psize = sizeof (void (*) ());

// 为函数指针声明类型定义
typedef void (*pfv) ();

pfv是一个函数指针,它指向的函数没有输入参数,返回类行为void。使用这个类型定义名可以隐藏复杂的函数指针语法。

指针变量应该有一个变量名:

void (*p) (); //p是指向某函数的指针

p是指向某函数的指针,该函数无输入参数,返回值的类型为void。左边圆括弧里星号后的就是指针变量名。有了指针变量便可以赋值,值的内容是署名匹配的函数名和返回类型。例如:

void func()
{
/* do something */
}
p = func;

p的赋值可以不同,但一定要是函数的地址,并且署名和返回类型相同。

传递回调函数的地址给调用者

现在可以将p传递给另一个函数(调用者)- caller(),它将调用p指向的函数,而此函数名是未知的:

void caller(void(*ptr)())
{
ptr(); /* 调用ptr指向的函数 */
}
void func();
int main()
{
p = func;
caller(p); /* 传递函数地址到调用者 */
}

如果赋了不同的值给p(不同函数地址),那么调用者将调用不同地址的函数。赋值可以发生在运行时,这样使你能实现动态绑定。

调用规范

到目前为止,我们只讨论了函数指针及回调而没有去注意ANSI C/C++的编译器规范。许多编译器有几种调用规范。如在Visual C++中,可以在函数类型前加_cdecl,_stdcall或者_pascal来表示其调用规范(默认为_cdecl)。C++ Builder也支持_fastcall调用规范。调用规范影响编译器产生的给定函数名,参数传递的顺序(从右到左或从左到右),堆栈清理责任(调用者或者被调用者)以及参数传递机制(堆栈,CPU寄存器等)。

将调用规范看成是函数类型的一部分是很重要的;不能用不兼容的调用规范将地址赋值给函数指针。例如:

// 被调用函数是以int为参数,以int为返回值
__stdcall int callee(int);

// 调用函数以函数指针为参数
void caller( __cdecl int(*ptr)(int));

// 在p中企图存储被调用函数地址的非法操作
__cdecl int(*p)(int) = callee; // 出错


指针p和callee()的类型不兼容,因为它们有不同的调用规范。因此不能将被调用者的地址赋值给指针p,尽管两者有相同的返回值和参数列。

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

如果把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,那就说这是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。

不管怎么说,回调函数是继承自C语言的。在C++中,应只在与C代码建立接口或与已有的回调接口打交道时,才使用回调函数。除了上述情况,在C++中应使用虚拟方法或仿函数(functor),而不是回调函数。

扩展资料

回调函数的好处:

1、回调函数可以把调用者与被调用者分开,所以调用者不关心谁是被调用者。它只需知道存在一个具有特定原型和限制条件的被调用函数。简而言之,回调函数就是允许用户把需要调用的函数的指针作为参数传递给一个函数,以便该函数在处理相似事件的时候可以灵活的使用不同的方法。

2、回调可用于通知机制。例如,有时要在A程序中设置一个计时器,每到一定时间,A程序会得到相应的通知,但通知机制的实现者对A程序一无所知。那么,就需一个具有特定原型的函数指针进行回调,通知A程序事件已经发生。实际上,API使用一个回调函数SetTimer()来通知计时器。

参考资料来源:百度百科-回调函数



回调函数就是你写好一个函数,让预先写好的系统来调用。你去调用系统的函数,是直调。让系统调用你的函数,就是回调。但假如满足于这种一句话结论,是不会真正明白的。

回调函数可以看成,让别人做事,传进去的额外信息。

比如,A 让 B 做事,根据粒度不同,可以理解成 A 函数调用 B 函数,或者 A 类使用 B 类,或者 A 组件使用 B 组件等等。反正就是 A 叫 B 做事。

当 B 做这件事情的时候,自身的需要的信息不够,而 A 又有。就需要 A 从外面传进来,或者 B 做着做着主动向外面申请。对于 B 来说,一种被动得到信息,一种是主动去得到信息,有人给这两种方式术语,叫信息的 push,和信息的 pull。

A 调用 B,A 需要向 B 传参数。如简单的函数:
int max(int a, int b);

要使用这函数,得到两者最大的值, 外面就要传进来 a, b。这个很好理解。

void qsort(void *, size_t, size_t, int (*)(const void *, const void *));

而这个函数用于排序,最后一个参数就是回调函数,似乎就比较难以理解了。这是因为人为割裂了代码和数据。

我们暂停一下,看看计算机中比较诡异的地方,也就是代码(code)和数据(data)的统一。这是一个槛,如果不打通这个,很多概念就不清楚。我们常常说计算机程序分成 code 和 data 两部分。很多人就会觉得,code 是会运行的,是动的,data 是给 code 使用,是静态的,这是两种完全不同的东西。

其实 code 只是对行为的一种描述,比如有个机器人可以开灯,关灯,扫地。如果跟机器人约定好,0 表示开灯,1 表示关灯,2 表示扫地。我发出指令串,0 1 2,就可以控制机器人开灯,关灯,扫地。再约定用二进制表示,两位一个指令,就有一个数字串,000111,这个时候 000111 这串数字就描述了机器人的一系列动作,这个就是从一方面理解是 code,它可以控制机器人的行为。但另一方面,它可以传递,可以记录,可以修改,也就是数据。只要大家都协商好,code 就可以编码成 data, 将 data 解释运行的时候,也变成了 code。

code 和 data 可以不用区分,统一称为信息。既然 int max(int a, int b) 中 int,double 等表示普通 data 的东西可以传递进去,凭什么表示 code 的函数就不可以传进去了。有些语言确实是不区分的,它的 function(表示code)跟 int, double 的地位是一样的。这种语言就为函数是第一类值。

而有些语言是不能存储函数,不能动态创建函数,不能动态销毁函数。只能存储一个指向函数的指针,这种语言称为函数是第二类值。

另外有些语言不单可以传递函数,函数里面又用到一些外部信息(包括code, data)。那些语言可以将函数跟函数所用到的信息一起传递存储。这种将函数和它所用的信息作为一个整体,就为闭包。

将代码和数据打通,统一起来。过了这个槛,很多难以理解的概念就会清晰很多。

现在我们再回头看看回调函数。回调函数也就是是 A 让 B 做事,B 做着做着,信息不够,不知道怎么做了,就再让外面处理。

比如上述排序例子,A 让 B 排序,B 会做排序,但排序需要知道哪个比哪个大,这点 B 自己不知道,就需要 A 告诉它。而这种判断那个大,本身是一种动作,既然 C 语言中不可以传进第一值的函数,就设计成传递第二值的函数指针,这个函数指针就是 A 传向 B 的信息,用来表示一个行为。这里本来 A 调用 B 的,结果 B 又调用了 A 告诉它的信息,也就叫 callback。

再比如 A 让 B 监听系统的某个消息,比如敲了哪个键。跟着 B 监听到了,但它不知道怎么去处理这个消息,就给外面关心这个消息,又知道怎么去处理这个消息的人去处理,这个处理过程本身是个行为,既然这个语言不可以传递函数,又只能传一个函数指针了。假如我将函数指针存储下来,以后就可以随时调用。代码和数据都是信息,数据可以存储下来,用来表示行为的函数自然也可以存储下来。

跟着有些人有会引申成,什么注册啊,通知啊等等等。假如 B 做监听,C, D, E, F, G, H 告诉 B 自己有兴趣知道这消息,那 B 监听到了就去告诉 C,D,E,F,G等人了,这样通知多人了,就叫广播。

其实你理解了,根本不用去关心术语的。术语是别人要告诉你啊,或者你去告诉人啊,使用的一套约定的词语。本质上就这个东西,结果会有很多术语的。

跟着再将回调的概念泛化,比如某人同时关心 A, B, C, D, E, F 事件,并且这些事件是一组的,比如敲键盘,鼠标移动,鼠标点击等一组。将一组事件结合起来。在有些语言就映射成接口,接口有 N 个函数。有些语言就映射成一个结构,里面放着 N 个函数指针。跟着就不是将单个函数指针传进去,而是将接口,或者函数指针的结构传进去。根据不同的用途,有些人叫它为代理,监听者,观察者等等。

实际上也是将某种行为存储下来,以后有需要再进行调用。跟回调函数在更深层次是没有区别的。

回调是指在价格上涨的趋势中,由于价格上涨过快,卖方打压,价格暂时回落的现象。回调小于涨幅,回调后将恢复上涨趋势。
股票回调注意事项:
1.不要盲目杀生。在股市崩盘的时候,不计成本的盲目减仓是不明智的。止损点要选择目前浅,上涨空间小的股票。对于目前下跌过快的股票,不妨等待其反弹后再择机卖出。
2.不要急着抢篮板。不要急于反弹是股市做回调时你必须知道的一点。尤其是在下跌的行情中,急于反弹就像是火中取栗。如果你稍有不慎,你可能会烧伤。目前市场环境下,不存在踏空的可能,所以股票投资者千万不要被蝇头小利套牢。
3.不要太惊慌。恐慌是投资者在大跌时最常见的情绪。股市涨就跌,跌就涨。其实这是自然规律。只要股市还在,就不会永远走低。毕竟最终还是要涨的。股市低迷时,投资者要好好学习,积极选股,尽早做好牛市的准备,避免市场回暖时追涨杀跌的老习惯。这就是在股市处于回调时如何进行股票交易。
4.不要急于挽回损失。股市中的投资者往往被套严重,账面亏损巨大,部分投资者急于挽回损失,随意增加操作频率或投入更多资金2。这样不仅无效,还会加重损失。当市场走势较弱时,投资者应尽量少操作或不操作股票,等待市场回暖。趋势明朗后介入更安全可靠。
5.不要太心急。一些新股民容易自暴自弃,甚至在暴跌行情中发火砸锅。但别忘了,再愤怒的人,过一会儿总能冷静下来。如果资本遭受重大损失,将很难收回投资。所以,任何情况下,投资者都不能把气撒在自己的资金账户上。
6.不要太后悔。后悔心理往往会让投资者陷入不断操作失误的恶性循环。所以投资者要尽快摆脱后悔心理的束缚,从失败中吸取教训,提高自己的操作水平,争取在以后的操作中不犯或少犯错误。

回调函数指的事先定义好的函数,当满足某个条件的时候,该函数才会被调用执行,回调函数多常用于网络编程中,因为网络是数据的到达是不可预知,故提前安排函数,一旦底层操作系统收到网络事件,会自动调用我们事先准备好的处理函数.这个你可以微信关注黑马设计师.那里有很多热心的老师实时在线帮助你答疑解惑.

回调函数:这个函数中,会检查请求的状态,如果请求的状态完成,并且没有发现服务端出现错误,那么将会从该服务器返回的数据进行处理并且通常以某种形式显示输出到页面上──JavaScript学习指南。


回调函数是什么
回调函数是一个程序员不能显式调用的函数,通过将回调函数的地址传给调用者从而实现调用。要实现回调,必须首先定义函数指针。调用规范影响编译器产生的给定函数名,参数传递的顺序,堆栈清理责任以及参数传递机制。

回调函数(callback)是什么?一文理解回调函数(callback)
回调函数是一种在程序执行过程中作为参数传递的特殊函数,它在被调用函数完成后执行,常用于异步编程、事件处理和API调用。其核心作用是处理异步操作的结果,将代码逻辑分解,提高代码的模块性和可维护性。回调函数的应用广泛,例如在异步网络编程中,当数据接收完成,回调函数会被触发处理数据;在GUI编程中,...

请问什么叫做回调函数
回调函数就是callback函数。是系统给用户的开放接口程序。当某事件发生时,系统需要处理这一事件,例如键盘输入事件发生,例如屏幕图像更新事件发生,如果你给了“回调函数”,系统则用你给的程序去处理,如果没给,系统就用默认方法处理。OpenGL 的 GLUT 程序就是这样。例如函数:glutDisplayFunc(display);...

什么是回调函数,如何写一个回调函数
什么是回调函数?回调函数是应用程序提供给Windows系统DLL或其它DLL调用的函数,一般用于截获消息、获取系统信息或处理异步事件。应用程序把回调函数的地址指针告诉DLL,而DLL在适当的时候会调用该函数。回调函数必须遵守事先规定好的参数格式和传递方式,否则DLL一调用它就会引起程序或系统的崩溃。通常情况下,...

什么是回调函数
回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用为调用它所指向的函数时,我们就说这是回调函数。也可以说回调函数是应用程序提供给Windows系统DLL或其它DLL调用的函数,一般用于截获消息、获取系统信息或处理异步事件。

在java里什么是回调函数啊.?
回调函数在Java中的定义 在Java中,回调函数是一种编程技术,指的是将一个函数作为参数传递给另一个函数,并在需要的时候由另一个函数调用的技术。被调用的函数称为回调函数。这种机制允许程序中的某些操作完成后,自动调用预设的函数来完成特定的任务。回调函数的实质是通过函数指针或者引用实现的程序间的...

什么是回调函数
结论:回调函数是一种特殊的函数调用方式,它允许一个函数接收另一个函数作为参数,并在特定的事件或条件满足时,由接收函数执行该传递的函数。这种机制源自C语言,但在C++中,除非是与C接口兼容或处理已有的回调,通常推荐使用虚拟方法或仿函数。回调函数的核心在于分离调用者与被调用者,调用者无需关心...

回调函数(callback)是什么?
当我们面对不可预测的事件,比如网络请求的响应,我们不能坐等结果。这时,我们会设定一个处理流程,即回调函数,预先定义好如何处理这个事件。这个流程就像是一个待办事项列表,当事件发生时,程序会按照这个清单进行操作,而这个操作的过程就是回调函数的调用。以购物为例,想象你在网店下单,但商品暂时缺货...

什么是回调函数
回调函数是一种设计模式,它巧妙地将调用者与被调用者之间的依赖关系解耦。在编程中,调用者并不关心具体是哪个函数被调用,只需知道存在一个具有特定接口和约束(比如返回类型为int)的函数可供调用。以音频采集为例,当数据被采集完成后,采集模块会自动调用一个回调函数,通知使用者数据已准备好。使用...

在JAVA里 什么是回调函数啊.?
在Java编程中,回调函数是一种设计模式,它允许一个对象在完成特定任务后,调用另一个对象的指定方法。简单来说,这是通过一个对象(客户程序C)调用另一个对象(服务程序S)的函数A,然后在合适的时候,服务程序S会调用客户程序C预先定义的函数B,这个B函数就是回调函数。回调在处理异步操作时特别有用...

铁锋区17147207035: 回调函数(被作为参数的函数) - 搜狗百科
帛帘捷赐: 回调函数是应用程序提供给Windows系统DLL或其它DLL调用的函数,一般用于截获消息、获取系统信息或处理异步事件.应用程序把回调函数的地址指针告诉DLL,而DLL在适当的时候会调用该函数.回调函数必须遵守事先规定好的参数格式和传递方式,否则DLL一调用它就会引起程序或系统的崩溃.通常情况下,回调函数采用标准WindowsAPI的调用方式,即__stdcall,当然,DLL编制者可以自己定义调用方式,但客户程序也必须遵守相同的规定.在__stdcall方式下,函数的参数按从右到左的顺序压入堆栈,除了明确指明是指针或引用外,参数都按值传递,函数返回之前自己负责把参数从堆栈中弹出.

铁锋区17147207035: 什么是回调函数 -
帛帘捷赐: 回调函数就是一个通过函数指针调用的函数.如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数.回调函数不是由该函数的实现方法直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应.

铁锋区17147207035: 在JAVA里 什么是回调函数啊.? -
帛帘捷赐: 所谓回调,就是客户程序C调用服务程序S中的某个函数A,然后S又在某个时候反过来调用C中的某个函数B,对于C来说,这个B便叫做回调函数. SAX的我不会写,只会用DOM4J写解析xml文档的例子 如下:SAXReader sax = new ...

铁锋区17147207035: 关于回调函数的详细讲解
帛帘捷赐: 回调函数2010年03月09日 星期二 上午 10:20 对指针的应用是C语言编程的精髓所在,而回调函数就是C语言里面对函数指针的高级应用.简而言之,回调函数是一个通过函数指针调用的函数.如果你把函数指针(函数的入口地址)传递给另一...

铁锋区17147207035: js中什么是回调函数 -
帛帘捷赐: 在计算机程序设计中,回调函数,或简称回调,是指通过函数参数传递到其它代码的,某一块可执行代码的引用.这一设计允许了底层代码调用在高层定义的子程序.

铁锋区17147207035: Java 什么是回调 -
帛帘捷赐: 所谓回调,就是客户程序Client调用服务程序Service中的某个方法A,然后Service又在某个时候反过来调用Client中的某个方法B,对于Client来说,这个B便叫做回调函数回调实现的步骤1、定义回调接口和回调方法 2、Client实现回调接口和回调方法,并在Client中包含Service引用,通过引用调用Servie中的方法并且必须传入一个当前对象Client(因为当前对象实现了CallBack接口所以也属于接口对象) 3、在Service中定义一个接口对象并在方法中对初始化(将Client传过来的当前对象赋值给接口对象),通过接口对象调用接口中方法(调用的Client实现的接口方法) 4、测试

铁锋区17147207035: 请问什么叫java中的回调函数? -
帛帘捷赐: 回调函数就是一个通过函数指针调用的函数.如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用为调用它所指向的函数时,我们就说这是回调函数.回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应.

铁锋区17147207035: 回调函数是什么 -
帛帘捷赐: 回调函数 程序员常常需要实现回调.本文将讨论函数指针的基本原则并说明如何使用函数指针实现回调.注意这里针对的是普通的函数,不包括完全依赖于不同语法和语义规则的类成员函数(类成员指针将在另文中讨论). 声明函数指针 回调...

铁锋区17147207035: 如何定义回调函数
帛帘捷赐: 回调不是被触发的,它在两个对象之间建立一个关系,使得一个可以对另一个做出反应.确切来说,它是一种代码的设计模式,让两个对象交互.给你个例子吧: //delegate定义 public delegate void ADelegate(int code, string data); //函数定义 public void CallBackMethod(int code,string data) { MessageBox.Show( "callback function! "); } //调用方法 ADelegate adelegate=new ADelegate(this.CallbackMethod);

本站内容来自于网友发表,不代表本站立场,仅表示其个人看法,不对其真实性、正确性、有效性作任何的担保
相关事宜请发邮件给我们
© 星空见康网