Ask the C++ Pro 10-Minute Solution (转)

Ask the C++ Pro 10-Minute Solution (转)[@more@] Ask the C++ Pro 10-Minute Solution
CSDN_Dev_Image_a%20href=2003-11-301754351.gif" width=400 border=0>
Declaring Function Pointers and Implementing Callbacks
By Danny Kalev

Programmers often need to implement callbacks. I will discuss the fundamentals of function pointers and show how to use them to implement callbacks. Notice that this article focuses on ordinary functions, not class member functions, which rely on substantially different syntactic and semantic rules (pointers to class members were discussed in a previous tips/cpp_pro/10min/10minJuly98.ASP" target='_"blank"'>10-Minute Solution).

Declaring a Function Pointer
A callback function is one that is not invoked explicitly by the programmer; rather the responsibility for its invocation is delegated to another function that receives the callback function's address. To implement a callback, you need to define an appropriate function pointer first. Although the syntax is a bit arcane, if you're familiar with function declarations in general, you will notice that a function pointer declaration is very similar to a function declaration. Consider the following example:

void f(); // a function prototype

 
 

It declares a function f() that takes no arguments and returns void. A pointer to such a function has the following type:

void (*) ();

 
 

Let's parse it. The asterisk in the leftmost parentheses is the nucleus of a function pointer declaration. Two additional elements are the function's return type, which appears on the left and is 'void' in our example, and a parameter list enclosed in the rightmost parentheses. In our case, the parameter list is empty because f() takes no arguments. Note that we didn't create a pointer variable yet—we only declared the type of such a variable. We can use this type to create a typedef name, or in a sizeof expression:

// get the size of a function pointer unsigned psize = sizeof (void (*) ());

// declare a typedef for a function pointer typedef void (*pfv) ();

 
 

pfv is a synonym for "a pointer to a function that takes no arguments and returns void". We can use this typedef name to hide the cumbersome syntax of function pointers.

A pointer variable, of course, has a name. Here is an example of such a pointer:

void (*p) (); // p is a pointer to a function

 
 

p is a pointer to a function that takes no arguments and returns void. The name of a pointer variable appears on the right of the asterisk, inside the parentheses. We can now assign a value to p. A value is simply a name of a function that has a matching signature (parameter list) and return type. For example:

void func() { /* do something */ } p = func;

 
 

You can assign a different value to p as long as it's the address of a function with the same signature and return type. A function's name is not a part of its type, though.

Passing an Address of a Callback Function to Its Caller
Now we can pass p to another function, caller(), which will call the function to which p points (the callee) without knowing its name:

void caller(void(*ptr)()) { ptr(); /* call the function to which ptr points */ } void func(); int main() { p = func; caller(p); /* pass address of func to caller */ }

 
 

If you assign a different function to p, caller() will invoke that function. The assignment can take place at runtime, which enables you to implement dynamic binding.

Calling Conventions
Up until now, we've discussed function pointers and callbacks without discussing compiler-specific conventions that aren't defined by ANSI C/C++. Many compilers have several calling conventions. For example, in Visual C++ you can precede __cdecl, __stdcall or __pascal to a function's type to indicate its calling convention (__cdecl is the default). C++ Builder also supports the __fastcall calling convention. The calling convention affects the compiler-generated name of a given function (i.e., name mangling), the order in which arguments are passed (right to left or left to right), stack cleanup responsibility (by the caller or the callee), and the mechanism for argument passing (stack, cpu registers, etc.).

It's important to note that the calling convention is an integral part of a function's type; you can't assign an address of a function to a pointer with an incompatible calling convention. For example:

// callee is a function that takes int and returns int __stdcall int callee(int); // caller is a function that takes a function pointer void caller( __cdecl int(*ptr)(int)); // illegal attempt to store the address of callee in p __cdecl int(*p)(int) = callee; // error

 
 

p and callee() have incompatible types because they have different calling conventions. Therefore, you can't assign callee's address to the pointer p, although both have the same return value and parameter list.


来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/10752019/viewspace-985678/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/10752019/viewspace-985678/

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值