一、调用和回调的定义

回调函数有点绕,可用简单的一个案例说明:

  • A给B打电话,问:1+1等于几? B说,我也忘了,我得想一会,想好了再告诉你。这时比较好的方式是断开电话链接,等B想好了再告诉A。于是他们挂断了电话,A又去忙别的事情,B算好了答案,给A打电话,告诉A结果等于2。
  • 上述,开始A给B打电话,后来,B想好了答案主动给A打电话的过程就是回调。

1.1 调用

  • 同步调用, 是一种阻塞式调用,调用方要等待对方执行完毕才返回,它是一种单向调用;
  • 异步调用, 是一种类似消息或事件的机制,不过它的调用方向刚好相反, 接口的服务在收到某种讯息或发生某种事件时,会主动通知客户端(即调用客户端的接口)。

1.2 回调

  • 回调, 是一种双向调用模式,也就是说,被调用方在接口被调用时也会调用对方的接口;
  • 回调和异步调用的关系非常紧密,通常我们使用回调来实现异步消息的注册,通过异步调用来实现消息的通知。
  • 同步调用是三者当中最简单的,而回调又常常是异步调用的基础,

1.3 架构回调实现

下面我们集中比较具有代表性的语言(C)和架构(C++)来分析回调的实现方式、具体作用等。

1.3.1 函数指针

1.函数和函数指针:

//1111111111111111111
void Func(char *s);// 函数原型
void (*pFunc) (char *);//函数指针//222222222222222222
int* func(int params, ...); //这就是指针函数

2.可以看出,函数的定义和函数指针的定义非常类似。 一般的化,为了简化函数指针类型的变量定义,提高程序的可读性,我们需要把函数指针类型自定义一下

//1111111111111111111
typedef void(*pcb)(char *);//222222222222222222
// 为回调函数命名,类型命名为 CallBackFun,参数为char *p 。
typedef int (*CallBackFun)(char *p);

3.回调函数可以象普通函数一样被程序调用,但是只有它被当作参数传递给被调函数时才能称作回调函数。
被回调函数的案例:

//11111111111111111
void GetCallBack(pcb callback)
{/*do something*/
}//2222222222222222
//下面的这些是调用者:有几种方式,看你喜欢哪种
int call(CallBackFun pCallBack, char *p){    // 执行回调函数,方式一:通过命名方式
printf("call 直接打印出字符%s!\n", p);
pCallBack(p);
return 0;
}
int call2(char *p, int (*ptr)())
{     // 执行回调函数,方式二:直接通过方法指针
printf("==============\n", p);
(*ptr)(p);
}
int call3(char *p, CallBackFun pCallBack){      // 执行回调函数,方式一:通过命名方式
printf("--------------\n", p);
pCallBack(p);
}

4.用户在调用上面的函数时,需要自己实现一个pcb类型的回调函数:

//111111111111111
void fCallback(char *s)
{/* do something */
} //222222222222222
int CallBackFun(char * p){//TODO
}

5.然后,就可以直接把fCallback当作一个变量传递给GetCallBack,

//1111111111111
GetCallBack(fCallback);//2222222222
//关联

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

1.3.2 参数传递规则

  • 到目前为止,我们只讨论了函数指针及回调而没有去注意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; // 出错, 前者是__cdecl ,后者是__stdcall

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

1.4 回调函数的优缺点

1.4.1 优点

  • 很多时候回调函数可以用来执行条件驱动的任务。即当该回调函数关心的那个条件被触发时,回调函数将被执行。条件触发可以是某一时间到了或者某一事件发生或者某一中断触发。

  • 回调函数不是由该函数的实现方直接调用,而是在特定的条件发生时由另外的一方调用的,用于对该事件或条件进行响应。

  • 使程序设计更灵活。允许用户把需要调用的方法的指针作为参数传递给一个函数,以便该函数在处理相似事件的时候可以灵活的使用不同的方法。而且这一设计允许了底层代码调用在高层定义的子程序。

  • 回调函数最大的优势应用就是异步回调。

  • 程序变成异步的了,也就是你不必再调用这个函数的时候一直等待这个时间的到达、事件的发生或中断的发生(万一一直不发生,你的程序会怎么样?)

  • 在此期间你可以做别的事情,或者四处逛逛。当回调函数被执行时,你的程序重新得到执行的机会,此时你可以继续做必要的事情了。

1.4.2 缺点

  • 学习成本会比普通函数高,需要有一定的抽象思维能力,需要对应用场景的理解。
  • 回调函数很多情况下会附带有跨线程操作甚至于跨进程的操作,这些都是异步带来的成本。

2.案例

// 类A
class A{public:
//A 的构造函数
A(){}
//函数指针类型自定义一下
typedef std::function<void(const std::shared_ptr<Submap2D>&)> UpdateFinishSubmapCallback;//Test 函数,某种情况下会调用回调函数
void Test(){std::shared_ptr<Submap2D> submaps;
if(submaps)SetUpdateSubmapCallback(submaps);
}
//
void SetUpdateSubmapCallback(UpdateFinishSubmapCallback callback) {updateFinishSubmapCallback_ = callback;}
private:
//定义回调函数对象
UpdateFinishSubmapCallback updateFinishSubmapCallback_;}class B{public:
A a_;
B(){// B 构造时,将回调函数关联起来 UpdateFinishSubmapCallback  std::placeholders::_1 指一个参数  ,多个参数 std::placeholders::_2...a_.SetUpdateSubmapCallback(std::bind(&A::UpdateFinishSubmapCallback, this, std::placeholders::_1));
}
void spin(){void (
// TODO
a_.Test();
}
private:
//声明和定义回调函数
bool UpdateFinishSubmapCallback(const std::shared_ptr<Submap2D>& submap){//TODO
}
}B b;
b.spin();
  1. 当B类调用 函数spin()时,会调用A中的 Test() 函数
  2. A中 Test() 一定条件会调用A的函数SetUpdateSubmapCallback()
  3. A的函数SetUpdateSubmapCallback() 调用回调函数 UpdateFinishSubmapCallback;
  4. A的UpdateFinishSubmapCallback 回调函数在B中调用,会调用B中bool
  5. UpdateFinishSubmapCallback(const std::shared_ptr& submap){} 函数

callback 回调函数相关推荐

  1. javascript~callback回调函数

    函数是对象,所以它可以作为一个参数传递给其他函数. 回调函数作为一个参数传递给其他函数时是没有括号的,只有函数名:使用括号表示立即执行回调函数callback.我们只希望传递一个函数的引用,让其他函数 ...

  2. js接收php 回调,JS callback回调函数的使用(附代码)

    这次给大家带来JS callback回调函数的使用(附代码),JS callback回调函数使用的注意事项有哪些,下面就是实战案例,一起来看一下. 在使用开源项目的时候经常会使用到回调函数,如果把回调 ...

  3. 十一、【TF2】Callback 回调函数

    TF2 Callback 一.回调函数简介 二.TF2中的内置回调函数 1- tf.keras.callbacks.BaseLogger 基础日志 2- tf.keras.callbacks.Hist ...

  4. php callback,php Callback 回调函数详解

    自 PHP 5.4 起可用 callable 类型指定回调类型 callback.本文档基于同样理由使用 callback 类型信息. 一些函数如 call_user_func() 或 usort() ...

  5. callback(回调函数)

    先讲点题外话. 编程分为两类:系统编程(system programming)和应用编程(application programming).所谓系统编程,简单来说,就是编写库:而应用编程就是利用写好的 ...

  6. Callback回调函数介绍(C语言)

    目录 1. 回调函数的定义 2. 为什么要用回调函数 3. 怎么用回调函数 3.1 怎么使用没有参数的回调函数 3.2 怎么使用带参数的回调函数 1. 回调函数的定义 最近在工作中经常用到回调函数ca ...

  7. c语言 callback回调函数

    你到一个商店买东西,刚好你要的东西没有货,于是你在店员那里留下了你的电话,过了几天店里有货了,店员就打了你的电话,然后你接到电话后就到店里去取了货.在这个例子里,你的电话号码就叫回调函数,你把电话留给 ...

  8. dispatch callback ant design pro 网络请求回调函数

    index.jsx 代码解析:在组件初次渲染时调用 model 中 命名空间为  a_models  的 getData 网络请求,传了一个patload 参数和 callback 回调函数过去,然后 ...

  9. JavaScript 回调(callback)函数

    此文适合JavaScript入门级选手阅读,高手就可以飘过了. 先扯点闲话.在中国,有这么一种现象:不管什么词或者概念,总会有些人把这些东西解释的神乎其神,貌似搞得别人听不懂就觉得自己很厉害的样子.其 ...

最新文章

  1. 鸡肋的PHP单例模式
  2. 2021-7-26 pytorch深度学习框架学习
  3. camel_Apache Camel 2.14中的更多指标
  4. autosys虚拟机定义
  5. Android AudioTrack/AudioRecord -wav文件读取3
  6. linux SVN web 同步
  7. 八进制数转十进制计算机计算器,八进制转十进制计算器
  8. python转换excel 列号 为数字 数字转为列号
  9. html制作图片幻灯片效果代码,【JS+CSS3】实现带预览图幻灯片效果的示例代码
  10. AppWeb认证绕过漏洞(CVE-2018-8715)漏洞复现
  11. 中小学计算机培训心得体会,中小学计算机管理员培训心得体会材料
  12. 弗洛伊德(Floyd)算法详解
  13. 为什么不建议使用免费的IP代理?
  14. C语言反序输出英文句子,iOS开发-英文句子倒序输出
  15. .net 本地文件管理 代码_如何在百万行代码中发现隐藏的后门
  16. oracle财务软件导出报表,OracleFusion财务会计中心报表云服务-UAO.PDF
  17. 未来时代量计算机科幻游戏,“八本科幻未来时代小说”到那个我们可以想象的极限,享受科幻美...
  18. 计算机图形学专业 国内大学排名,虚拟现实应用技术专业大学排名 2020全国排行榜...
  19. Google Earth Engine(GEE)——基本介绍和图像分析、可视化和处理实战
  20. iOS 逆向获取手机硬件参数

热门文章

  1. SAP AS ABAP 7.52 SP04, Developer Edition 免费下载
  2. 华为p10 android几,华为p10国行版和海外版有什么区别 配置参数对比评测
  3. (亲测解决)Tomcat启动时卡在“ Deploying web application directory ”很久的解决方法
  4. 如何评价唐卫国公李靖的战功、军事才能、政治才能?
  5. JAVA的if结构单分支结构简单易懂
  6. unity 实现手机震动
  7. 头文件中能否进行函数的定义
  8. 备份iphoneXR手机照片
  9. 开发常用到的工具有哪些
  10. 【论文学习】《“Hello, It’s Me”: Deep Learning-based Speech Synthesis Attacks in the Real World》