1、甚么是反弹表达式?
反弹表达式,光听英文名字就比一般表达式要矮小上一些,那究竟甚么是反弹表达式呢?恕我读得书少,没在两本书上看到有关反弹表达式的论述。我在腾讯上搜了一下,发现莫衷一是,有很大一部分都是采用类似这么两个情景来说明:A君去B君店门口买东西,正好断货,A君留下电话号码给B君,有C3A1通知A君。感觉那个让人更容易想到的是触发器操作,而并非反弹。
除此之外还有那段话英语让我第一印象真切:1) If you call me, I will call you back; 2) Dont call me, I will call you. 看上去好像很有规矩,但是细细一想,一般表达式不也能努力做到这点吗?所以,我真的这样的讲法都并非很恰当,因为我真的这些讲法都没把反弹表达式的特点唱出来,也是都看不出和一般表达式究竟有甚么差异。
不过,腾讯新浪网的导出我真的还算极好(虽然经常聊著腾讯搜寻…):反弹表达式是两个透过表达式操作符调用的表达式。假如你把表达式的操作符(门牌号)作为HTA给另两个表达式,当那个操作符被用以初始化其所对准的表达式时,他们就说这是反弹表达式。
上面先说说我的观点。他们能先在字面先做个降解,对于”反弹表达式”,英语其实可以理解为那么两种意思:1) 被反弹的表达式;2) 转头继续执行初始化姿势的表达式。那那个转头初始化又是甚么鬼?
嘿嘿看一看源自维基的对反弹(Callback)的导出:In computer programming, a callback is any executable code that is passed as an argument to other code, which is expected to call back (execute) the argument at a given time. This execution may be immediate as in a synchronous callback, or it might happen at a later time as in an asynchronous callback. 换句话说,把几段可继续执行的标识符像HTA那样传予其他标识符,而那段标识符会在某一关键时刻被初始化继续执行,这就叫作反弹。假如标识符立即被继续执行就称为并行反弹,假如在之后延误的某一时间再继续执行,则称作触发器反弹。有关并行和触发器,这里不作探讨,请翻查相关资料。
再来看一看源自Stack Overflow该位天神瑞维尼的论述:A “callback” is any function that is called by another function which takes the first function as a parameter。换句话说,表达式 F1 初始化表达式 F2 的时候,表达式 F1 透过模块给 表达式 F2 传达了除此之外两个表达式 F3 的操作符,在函数 F2 继续执行的过程中,表达式F2 初始化了表达式 F3,那个姿势就叫作反弹(Callback),而先被当作操作符传至、后面又被反弹的表达式 F3 是反弹表达式。到此应该明白反弹表达式的论述了吧?
2、为甚么要采用反弹表达式?
很多朋友可能会想,为甚么不像一般表达式初始化那样,在反弹的地方直接写表达式的英文名字呢?这样不也能吗?为甚么非得用反弹表达式呢?有那个想法很好,因为在网上看到导出反弹表达式的很多例子,其实完全能用一般表达式初始化来实现的。要回答那个问题,他们嘿嘿了解一下回到表达式的好处和作用,那是解耦,对,是那么简单的答案,是因为那个特点,一般表达式代替不了反弹表达式。所以,在我眼里,这才是反弹表达式最大的特点。来看一看维基上面我真的画得很好的一张图片。
乍一看,反弹似乎只是表达式间的初始化,和一般表达式初始化没啥区别,但细细一看,能发现两者之间的两个关键的不同:在回调中,主程序把反弹表达式像模块一样传至库表达式。这样一来,只要他们改变传进库表达式的模块,就能实现不同的功能,这样有没真的很灵活?并且丝毫不需要修改库表达式的实现,这是解耦。
再细细看一看,主表达式和反弹表达式是在同一层的,而库表达式在除此之外一层,想一想,假如库表达式对他们不可见,他们修改不了库表达式的实现,换句话说不能透过修改库表达式让库表达式初始化一般表达式那样实现,那他们就只能透过传至不同的反弹表达式了,这也是在日常工作中常见的情况。现在再把main()、Library()和Callback()表达式套回前面 F1、F2和F3表达式里面,是并非就更明白了?
明白了反弹表达式的特点,是并非也能大概知道它应该在甚么情况下使用了?没错,你能在很多地方采用反弹表达式来代替一般的表达式初始化,但是在我看来,假如需要降低耦合度的时候,更应该采用反弹表达式。3、怎么采用反弹表达式?
知道了甚么是反弹表达式,了解了反弹表达式的特点,那么应该怎么采用反弹表达式?上面来看几段简单的能继续执行的并行反弹表达式标识符。
运行结果:
Entering Main Function.
Entering Handle Function.
Hello, this is Callback_1
Leaving Handle Function.
Entering Handle Function.
Hello, this is Callback_2
Leaving Handle Function.
Entering Handle Function.
Hello, this is Callback_3
Leaving Handle Function.
Leaving Main Function.能看到,Handle()表达式里面的模块是两个操作符,在main()表达式里初始化Handle()表达式的时候,给它传至了表达式Callback_1()/Callback_2()/Callback_3()的表达式名,这时候的表达式名是对应表达式的操作符,换句话说,反弹表达式其实是表达式操作符的一种用法。现在再读一遍这句话:A “callback” is any function that is called by another function which takes the first function as a parameter,是并非就更明白了呢?
相关视频推荐
学习门牌号:c/c++ linux服务器开发/后台架构师
需要C/C++ Linux服务器架构师学习资料加qun812855908(资料包括C/C++,Linux,golang技术,内核,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,TCP/IP,协程,DPDK,ffmpeg,大厂面试题 等)
4、怎么采用带模块的反弹表达式?
眼尖的朋友可能发现了,前面的例子里面反弹表达式是没模块的,那么他们能不能反弹那些带模块的表达式呢?答案是肯定的。那么怎么初始化呢?他们稍微修改一下上面的例子就能了:
运行结果:
Entering Main Function.Entering Handle Function.Hello, this is Callback_1: x = 2Leaving Handle Function.Entering Handle Function.Hello, this is Callback_2: x = 4Leaving Handle Function.Entering Handle Function.Hello, this is Callback_3: x = 6Leaving Handle Function.Leaving Main Function.能看到,并并非直接把int Handle(int (*Callback)()) 改成 int Handle(int (*Callback)(int)) 就能的,而是透过除此之外增加两个模块来保存回调表达式的模块值,像这里 int Handle(int y, int (*Callback)(int)) 的模块 y。同理,能采用多个模块的反弹表达式。