总结CALLBACE函数

看了後先生的《深入浅出MFC》中的CALLBACKE函数,做一下总结.

以下是此书对CALLback的解释:
虽然现在来讲这个题目,对初学者而言恐怕是过于艰深,但我想毕竟还是个好机会
--- 我可以在介绍如何使用callback 函数的场合,顺便介绍一些C++ 的重要观念。
首先我要很快地解释一下什么是callback 函数。凡是由你设计而却由Windows 系
统调用的函数,统称为callback 函数。这些函数都有一定的类型,以配合Windows
的调用动作。
某些Windows API 函数会要求以callback 函数作为其参数之一,这些API 例如
SetTimer、LineDDA、EnumObjects。通常这种API 会在进行某种行为之后或满足某种
状态之时调用该callback 函数。图6-6 已解释过LineDDA调用callback 函数的时机;
下面即将示范的EnumObjects 则是在发现某个Device Context 的GDI object 符合我们
的指定类型时,调用callback 函数。
好,现在我们要讨论的是,什么函数有资格在C++ 程序中做为callback 函数?这个
问题的背后是:C++ 程序中的callback 函数有什么特别的吗?为什么要特别提出讨论?
是的,特别之处在于,C++ 编译器为类别成员函数多准备了一个隐藏参数(程序代码
中看不到),这使得函数类型与Windows callback 函数的预设类型不符。
假设我们有一个CMyclass 如下:
// 注册callback 函数
C++ 编译器针对CMyclass::enumIt 实际做出来的码相当于:
// 注册callback 函数
你所看到的最后一个参数,(CDC *)&dc,其实就是this 指针。类别成员函数靠着this
指针才得以抓到正确对象的资料。你要知道,内存中只会有一份类别成员函数,
但却可能有许多份类别成员变量--- 每个对象拥有一份。
C++ 以隐晦的this 指针指出正确的对象。当你这么做:
nCount = 0;
其实是:
this->nCount = 0;
基于相同的道理,上例中的EnumObjectsProc 既然是一个成员函数,C++ 编译器也
会为它多准备一个隐藏参数。
好,问题就出在这个隐藏参数。callback 函数是给Windows 调用用的,Windows 并
不经由任何对象调用这个函数,也就无由传递this 指针给callback 函数,于是导至
堆栈中有一个随机变量会成为this 指针,而其结果当然是程序的崩溃了。
要把某个函数用作callback 函数,就必须告诉C++ 编译器,不要放this 指针作为
该函数的最后一个参数。两个方法可以做到这一点:
1. 不要使用类别的成员函数(也就是说,要使用全域函数)做为callback 函数。
2. 使用static 成员函数。也就是在函数前面加上static 修饰词。
第一种作法相当于在C 语言中使用callback 函数。第二种作法比较接近OO 的精神。
我想更进一步提醒你的是,C++ 中的static 成员函数特性是,即使对象还没有产生,
static 成员也已经存在(函数或变量都如此)。换句话说对象还没有产生之前你已经
可以调用类别的static 函数或使用类别的static 变量了。请参阅第二章。
也就是说,凡声明为static 的东西(不管函数或变量)都并不和对象结合在一起,
它们是类别的一部份,不属于对象。

耐心看完之后觉得最重要的几句话就是最后的总结.
1. 不要使用类别的成员函数(也就是说,要使用全域函数)做为callback 函数。
2. 使用static 成员函数。也就是在函数前面加上static 修饰词。
第一种作法相当于在C 语言中使用callback 函数。第二种作法比较接近OO 的精神。
我想更进一步提醒你的是,C++ 中的static 成员函数特性是,即使对象还没有产生,
static 成员也已经存在(函数或变量都如此)。换句话说对象还没有产生之前你已经
可以调用类别的static 函数或使用类别的static 变量了。请参阅第二章。
也就是说,凡声明为static 的东西(不管函数或变量)都并不和对象结合在一起,
它们是类别的一部份,不属于对象.

另外在网上搜索了一些有帮助的帖子.....如下:

  其实CALLBACK函数一点也不神秘!他不过是一个普通函数而已!  
   
  有些中文参考书上把CALLBACK函数称为“回调函数”,表示WINDOWS调用的  
  位于用户进程空间中的函数,因此其调用约定必须与WINDOWS   API调用约定  
  一致,即为WINAPI,也即_stdcall.象WndProc,Enum***Proc  
  (EnumThreadProc,EnumProcessProc,EnumWindowsProc...)等都是CALLBACK  
  函数。  
   
  为了让WINDOWS调用你的CALLBACK函数,你必须把你的函数指针传给他:  
  WndProc要在RegisterClass(&WndClass)   的   WndClass   中指定;  
  EnumWindowProc   要在  
  EnumWindows(   WNDENUMPROC   lpEnumFunc, //   EnumWindowProc的指针  
                            LPARAM   lParam         //程序员指定的值,用来区分不同的  
                                                              //EnumWindows调用  
                          )  
  的lpEnumFunc中指定。  
   
  Windows   会在适当的时侯调用你的CALLBACK函数,如WndProc在窗口有消息  
  时被调用,EnumWindowProc在WINDOWS找到窗口时被调用。  
   
  CALLBACK函数并不象第3点说的那样象一个线程,就拿EnumWindowProc来说  
  吧:EnumWindows   要在EnumWindowProc   返回FALSE或所有窗口都被列举时才  
  返回,例如有以下代码:  
  BOOL   EnumwndProc(HWND   hwnd,LPARAM   lparam)  
  {  
          //Do   something   with   the   window   hwnd  
          return   TRUE;  
  }  
  void   func()  
  {  
      int   i;  
      EnumWindows(EnumwndProc,0);  
      i++;  
  }  
   
  func   中的   i++   在所有窗口都被列举前将不被执行。  

看完之后好像有些明白,继续学习....

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值