Chinaunix首页 | 论坛 | 博客
  • 博客访问: 103469
  • 博文数量: 27
  • 博客积分: 2510
  • 博客等级: 少校
  • 技术积分: 246
  • 用 户 组: 普通用户
  • 注册时间: 2008-08-02 22:35
文章分类

全部博文(27)

文章存档

2009年(13)

2008年(14)

我的朋友

分类: LINUX

2008-12-28 22:33:32

1. The call back declaration:
回调函数是一个程序员不能显式调用的函数;通过将回调函数的地址传给调用者从而实现调用。
要实现回调,必须首先定义函数指针。尽管定义的语法有点不可思议,
但如果你熟悉函数声明的一般方法,便会发现函数指针的声明与函数声明非常类似。
请看下面的例子:
 void f();//函数原型上面的语句声明了一个函数,没有输入参数并返回void。
那么函数指针的声明方法如下:
 void (*)();
让我们来分析一下,左边圆括弧中的星号是函数指针声明的关键。
另外两个元素是函数的返回类型和由边圆括弧中的入口参数。
注意本例中还没有创建指针变量-只是声明了变量类型。
目前可以用这个变量类型来创建类型定义名及用sizeof表达式获得函数指针的大小:
 //获得函数指针的大小
 unsigned psize = sizeof(void (*)());
 //为函数指针声明类型定义
 typedef void (*pfv)();
pfv是一个函数指针,它指向的函数没有输入参数,返回类行为void。
使用这个类型定义名可以隐藏复杂的函数指针语法。
指针变量应该有一个变量名:
 void (*p)(); //p是指向某函数的指针
p是指向某函数的指针,该函数无输入参数,返回值的类型为void。左边圆括弧里星号后的就是指针变量名。
有了指针变量便可以赋值,值的内容是署名匹配的函数名和返回类型。例如:
 void func()
 {
  /* do something */
 }
 p = func;
p的赋值可以不同,但一定要是函数的地址,并且署名和返回类型相同。
2. 传递回调函数的地址给调用者现在可以将p传递给另一个函数- caller(),
它将调用p指向的函数,而此函数名是未知的:
 void caller(void(*ptr)())
 {
  ptr(); /* 调用ptr指向的函数 */
 }
 void func();
 int main()
 {
  p = func;
  caller(p); /* 传递函数地址到调用者 */
 }
如果赋了不同的值给p,那么调用者将调用不同地址的函数。赋值可以发生在运行时,这样使你能实现动态绑定。
3. 调用规范到目前为止,我们只讨论了函数指针及回调而没有去注意ansi c/c++的编译器规范。
许多编译器有几种调用规范。如在visual c++中,可以在函数类型前加_cdecl,
_stdcall或者_pascal来表示其调用规范。c++ builder也支持_fastcall调用规范。
调用规范影响编译器产生的给定函数名,参数传递的顺序,堆栈清理责任以及参数传递机制。
将调用规范看成是函数类型的一部分是很重要的;不能用不兼容的调用规范将地址赋值给函数指针。例如:
 //被调用函数是以int为参数,以int为返回值
 __stdcall int callee(int); //调用函数以函数指针为参数
 void caller(__cdecl int(*ptr)(int)); //在p中企图存储被调用函数地址的非法操作
 __cdecl int(*p)(int) = callee; //出错指针p和callee()的类型不兼容,因为它们有不同的调用规范。因此不能将被调用者的地址赋值给指针p,尽管两者有相同的返回值和参数列。
 
发表者:james_razor callback function其实就是c语言中,strategy模式的一种实现。
阅读(1163) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~