回调函数详解

来源:互联网 发布:巨人网络集团董事长 编辑:程序博客网 时间:2024/05/01 11:57

解释1


callback这个词本意是打电话对方不在,通过某种方法让那个人在的时候给你打回来。

 

void f() { ... } 调用这个函数话...和回调没有任何关系。就相当于A:"B,你去干f。"

 

void f(int (*g)()) { ... g(); } 这个函数就带有回调的特征。调用的时候好像 A:"B,你去干f。干好了叫我干g。"

 

也就是调用方留一个让被调用方在特定时候通知他的线索,对他进行“回调”。 

 

----

 

接着上面说,f这个工作要求是干完以后干一件事g。但是这个g并不是f自己规定的,是在调用f的时候再告诉f的。比如你可以让B在完成的时候,什么也不干;或者叫你一声;或者让你干另外一件事。就是说g这个工作本身就是个变量。

 

----

 

如果不作为参数提供,g就成了f固定的一部分。A直接说“你去干f”不就是了。作为参数的意义就在于,这个g可以随意改变。 

 

----

 

解释2

 

首先做一个形象的比喻:

  你有一个任务,但是有一部分你不会做,或者说不愿做,所以我来帮你做这部分,你做你其它的任务工作或者等着我的消息,但是当我完成的时候我要通知你我做好了,你可以用了,我怎么通知你呢?你给我一部手机,让我做完后给你打电话,我就打给你了,你拿到我的成果加到你的工作中,继续完成其它的工作.这就叫回叫,手机是我通知你的手段,它就是回叫函数,也叫回调函数

  回调函数是应用程序提供给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调用。 

 

实例

 

     回调函数不是由你调用的,是系统提供给你让你去实现、去使用的。回调函数是被哪里调用的,在什么情况下调用的,你是不知道的,你只能实现这个函数,只要你实现了这个函数,你的程序就会使用到这个函数,而普通函数你的程序中如果不调用则不起作用。例如窗口过程函数,你的程序并不调用,但你需要实现这个函数,这样你的程序执行后,窗口过程函数就会起作用;如果你定义了一个普通函数fun,如果你的程序中并没有调用,那么在你的程序中fun这个函数就不会起作用。 

 

如下例子:

 

比如你要枚举所有的窗口。可以调用EnumWindows函数。但是,EnumWindows仅仅是将窗口枚举出来,至于如何处理则需要你来定义。

 

   就是说,当你调用EnumWindow,要指定一个回调函数,来告诉EnumWindow,当她枚举到窗口的时候,应该怎么处理这个窗口。

 

   CallBack( HWND wnd ... ) //EnumWindow的回调函数

   {

        //这里是自定定义的

        //假设设计目的是要找出标题为 “xxx”的窗口;

        CString str = GetWindowText( wnd );

        if( ! str.Compare( "xxx" ))

        {

            g_hWnd = wnd; // 保存这个窗口的句柄;

            return TRUE;  // 告诉EnumWindow不需要再继续枚举了。

        }

        else

            return FALSE; // 告诉EnumWindow,这次枚举到的

                          // 不是我要找的,还需要继续枚举下一个窗口。

   }

 

   ............某代码.............

   g_hWnd = NULL;    // 初始化保存所找窗口句柄的变量。

   EnumWindow(  CallBack ...... ); 调用枚举函数并指定回调函数。

   if( g_hWnd )

      // 说明已经找到了

   else

      // 依然没有找到。 

原创粉丝点击