`
wangleifire
  • 浏览: 509070 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

回调函数原理

    博客分类:
  • c#
阅读更多

回调函数原理

声明CALLBACK  

调用(calling)机制从汇编时代起已经大量使用:准备一段现成的代码,调用者可以随时跳转至此段代码的起始地址,执行完后再返回跳转时的后续 地址。CPU为此准备了现成的调用指令,调用时可以压栈保护现场,调用结束后从堆栈中弹出现场地址,以便自动返回。借堆栈保护现场,它使调用者和被调者可 以互不相识,于是才有了后来的函数和构件.  

此调用机制并非完美。回调函数就是一例。例如,写一个快速排序函数供他人调用,其中必包含比较大小。麻烦来了:此时并不知要比较的是何类数据--整 数、浮点数、字符串?于是只好为每类数据制作一个不同的排序函数。更通行的办法是在函数参数中列一个回调函数地址,并通知调用者:君需自己准备一个比较函 数,其中包含两个指针类参数,函数要比较此二指针所指数据之大小,并由函数返回值说明比较结果。排序函数借此调用者提供的函数来比较大小,借指针传递参 数,可以全然不管所比较的数据类型。被调用者回头调用调用者的函数(够咬嘴的),故称其为回调(callback)。

Windows系统还包含着另一种更为广泛的回调机制,即消息机制。消息本是Windows的基本控制手段,乍看与函数调用无关,其实是一种变相的函数调用。发送消息的目的是通知收方

运行一段预先准备好的代码,相当于调用一个函数。消息所附带的WParam和LParam相当于函数的参数,只不过比普通参数更通用一些。应用程序 可以主动发送消息,更多情况下是坐等 Windows发送消息。一旦消息进入所属消息队列,便检感兴趣的那些,跳转去执行相应的消息处理代码。操作系统本是为应用程序服务,由应用程序来调用。 而应用程序一旦启动,却要反过来等待操作系统的调用。这分明也是一种回调,或者说是一种广义回调。其实,应用程序之间也可以形成这种回调。假如进程B收到 进程A发来的消息,启动了一段代码,其中又向进程A发送消息,这就形成了回调。这种回调比较隐蔽,弄不好会搞成递归调用,若缺少终止条件,将会循环不已, 直至把程序搞垮。若是故意编写成此递归调用,并设好终止条件,倒是很有意思。但这种程序结构太隐蔽,除非十分必要,还是不用为好。

利用消息也可以构成狭义回调。上面所举排序函数一例,可以把回调函数地址换成窗口handle。如此,当需要比较数据大小时,不是去调用回调函数, 而是借API函数SendMessage   向指定窗口发送消息。收到消息方负责比较数据大小,把比较结果通过消息本身的返回值传给消息发送方。所实现的功能与回调函数并无不同。当然,此例中改为消 息纯属画蛇添脚,反倒把程序搞得很慢。但其他情况下并非总是如此,特别是需要异步调用时,发送消息是一种不错的选择。假如回调函数中包含文件处理之类的低 速处理,调用方等不得,需要把同步调用改为异步调用,去启动一个单独的线程,然后马上执行后续代码,其余的事让线程慢慢去做。一个替代办法是借   API函数PostMessage发送一个异步消息,然后立即执行后续代码。这要比自己搞个线程省事许多,而且更安全。

如今我们是活在一个object时代。只要与编程有关,无论何事都离不开object。但object并未消除回调,反而把它发扬光大,弄得到处都 是,只不过大都以事件(event)的身份出现,镶嵌在某个结构之中,显得更正统,更容易被人接受。应用程序要使用某个构件,总要先弄清构件的属性、方法 和事件,然后给构件属性赋值,在适当的时候调用适当的构件方法,还要给事件编写处理例程,以备构件代码来调用。何谓事件?它不过是一个指向事件例程的地 址,与回调函数地址没什么区别。不过,此种回调方式比传统回调函数要高明许多。首先,它把让人不太舒服的回调函数变成一种自然而然的处理例程,使编程者顿 觉气顺。再者,地址是一个危险的东西,用好了可使程序加速,用不好处处是陷阱,程序随时都会崩溃。现代编程方式总是想法把地址隐藏起来(隐藏比较彻底的如 VB和Java),其代价是降低了程序效率。事件例程使编程者无需直接操作地址,但并不会使程序减速。

 

自定义回调函数

回调函数是不能显式调用的函数;通过将回调函数的地址传给调用者从而实现调用。回调函数使用是必要的,在我们想通过一个统一接口实现不同的内容,这 时用回掉函数非常合适。比如,我们为几个不同的设备分别写了不同的显示函数:void TVshow(); void ComputerShow(); void NoteBookShow()...等等。这是我们想用一个统一的显示函数,我们这时就可以用回掉函数了。

    void show(void (*ptr)());

使用时根据所传入的参数不同而调用不同的回调函数。

不同的编程语言可能有不同的语法,下面举一个c语言中回调函数的例子,其中一个回调函数不带参数,另一个回调函数带参数。

例子1:

 

//Test.c

 

#include <stdlib.h>

#include <stdio.h>

 

int Test1()

{

   int i;

   for (i=0; i<30; i++)

   {

     printf("The %d th charactor is: %c\n", i, (char)('a' + i%26));

    }

   return 0;

}

int Test2(int num)

{

   int i;

   for (i=0; i<num; i++)

   {

    printf("The %d th charactor is: %c\n", i, (char)('a' + i%26));

    }

   return 0;

}

 

void Caller1(void (*ptr)())//指向函数的指针作函数参数

{

   (*ptr)();

}

void Caller2(int n, int (*ptr)())//指向函数的指针作函数参数,这里第一个参数是为指向函数的指针服务的,

{ //不能写成void Caller2(int (*ptr)(int n)),这样的定义语法错误。

   (*ptr)(n);

   return;

}

int main()

{

   printf("************************\n");

   Caller1(Test1); //相当于调用Test2();

   printf("&&&&&&************************\n");

   Caller2(30, Test2); //相当于调用Test2(30);

   return 0;

}

 

以上通过将回调函数的地址传给调用者从而实现调用,但是需要注意的是带参回调函数的用法。要实现回调,必须首先定义函数指针。函数指针的定义这里稍 微提一下。比如: int (*ptr)(); 这里ptr是一个函数指针,其中(*ptr)的括号不能省略,因为括号的优先级高于星号,那样就成了一个返回类型为整型的函数声明了。

=================================

转载地址:

注: 狐狸认为, 回调函数实现多态函数只是附带功能之一, 最主要是提供了一种代码动态嵌入的手段, 实现函数内部中断的一种方式.

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/woyaowenzi/archive/2009/03/02/3950116.aspx

分享到:
评论

相关推荐

    JS回调函数原理与用法详解【附PHP回调函数】

    本文实例讲述了JS回调函数原理与用法。分享给大家供大家参考,具体如下: JS回调函数 何为回调函数,官方解释:当程序跑起来时,一般情况下,应用程序(application program)会时常通过API调用库里所预先备好的函数...

    C# 实现回调函数

    接下来,我们将深入探讨C#中实现回调函数的原理、方式以及应用场景。 首先,我们需要理解什么是回调函数。回调函数本质上就是一个函数引用,可以在其他函数执行过程中或结束后被调用。在C#中,你可以通过几种方式来...

    回调函数演示

    描述中提到的“演示回调函数工作原理”意味着我们将深入到回调函数的实际操作中。首先,我们需要创建一个回调函数,它通常有一个特定的函数原型,以便能够与调用它的函数接口匹配。例如,在Windows API中,`LRESULT ...

    回调函数讲解

    ### 回调函数详解 #### 一、回调函数的基本概念 在计算机编程中,回调函数是一种特殊的函数,它被作为参数...通过理解和掌握回调函数的工作原理及其应用场景,开发者可以更高效地解决问题并构建出高质量的软件产品。

    回调函数详解

    #### 二、回调函数的工作原理 回调函数的工作原理基于函数指针的概念。当我们调用一个接受函数指针作为参数的函数时,实际上是传递了一个指向我们自定义函数的地址。这个被传递的函数(即回调函数)可以在适当的...

    轻松了解C语言回调函数

    下面我们将详细探讨C语言回调函数的原理、使用方法以及常见应用场景。 ### 回调函数的概念 回调函数的本质是一个可以被其他函数调用的函数,但它的调用权不在于自身,而是在另一个函数(通常称为“回调函数的调用...

    CC++中回调函数初探

    对于很多初学者来说,往往觉得回调函数很神秘,很想知道回调函数的工作原理。本文将要解释什么是回调函数、它们有什么好处、为什么要使用它们等等问题,在开始之前,假设你已经熟知了函数指针。    什么是回调...

    Delphi 回调函数范例

    通过学习这些实例,你可以更好地理解Delphi中回调函数的工作原理和使用方式。 总的来说,Delphi的回调函数机制为程序设计提供了更大的灵活性和可扩展性。通过掌握回调函数,开发者可以创建更加动态和响应的软件,...

    js回调函数原理与用法案例分析

    本文实例讲述了js回调函数原理与用法。分享给大家供大家参考,具体如下: 回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,...

    VC++回调函数使用

    本文将深入探讨VC++回调函数的基本概念、工作原理以及如何使用。 ### 回调函数的基本概念 回调函数的核心思想是将函数的指针作为参数传递给另一个函数。当被调用的函数执行到一定程度时,会使用这个传递的指针来...

    帮助理解回调函数的简洁实例

    让我们深入探讨回调函数的工作原理和应用场景。 1. **回调函数的概念** 回调函数的本质是一个函数引用,它作为参数传递给另一个函数。接收函数在适当的时候(通常是其内部任务完成后)调用这个回调。这种模式允许...

    简单的回调函数例子

    你可以通过编译和运行这些代码来更深入地理解回调函数的工作原理。 回调函数是C语言中实现复杂逻辑和灵活编程的重要工具,它们在多线程编程、图形用户界面事件处理、库接口设计等多个领域都有广泛的应用。理解并...

    vc回调函数举例

    在VC++编程环境中,回调函数是一种非常重要的机制,它允许我们定义一个函数,然后将这个函数的指针作为参数传递给另一个函数,被传递的函数在适当的时候会被调用执行。这种方式在多线程编程中尤其常见,因为它可以...

    C# Csharp 调用 C++的DLL中的回调函数

    本示例探讨的是如何在C#(Csharp)中调用C++动态链接库(DLL)中的回调函数。这涉及到C++导出函数、C# P/Invoke技术以及C#委托的理解和应用。 首先,我们需要理解C++的DLL工作原理。DLL是一种可重用的代码库,它...

    经典回调函数实例

    在“经典回调函数实例”中,我们可以想象一个朋友打电话的情景来理解回调函数的工作原理。假设你有一个朋友A,他想要告诉你一些消息,但他只能在电话接通后才能告诉你。因此,A不会立即告诉你消息,而是先打给你,当...

    Android回调函数demo

    在这个“Android回调函数demo”中,我们将深入探讨回调函数在Android应用中的运用及其工作原理。 首先,回调函数在Android中的核心应用场景是事件监听。例如,当我们点击一个按钮,我们希望执行一些操作。这时,...

    C++ 回调函数

    下面我们将深入探讨C++中的回调函数,包括其原理、实现方式以及在实际开发中的应用。 首先,我们需要了解函数指针,它是C++中实现回调的基础。函数指针是一个变量,它可以存储一个函数的地址,这样就可以在之后的...

    理解和使用 JavaScript 中的回调函数

    本文旨在深入探讨回调函数的概念、工作原理以及如何在实际开发中应用它们。 #### 一、回调函数的定义与特点 **定义:** 回调函数是一种特殊的函数,它作为参数传递给另一个函数,并且在这个外部函数执行过程中被...

Global site tag (gtag.js) - Google Analytics