科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道应用软件C/C 中回调函数初探

C/C 中回调函数初探

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

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

作者:谢启东编译 来源:天极开发  2007年9月14日

关键字:

  • 评论
  • 分享微博
  • 分享邮件

下面另有一个程序,用于测试以上所有的代码,它传递了一个有5个元素的数组给Bubblesort()和Quicksort(),同时还传递了一个指向回调函数的指针。

int main(int argc, char* argv[])

{

 int i;

 int array[] = {5432, 4321, 3210, 2109, 1098};

 cout << "Before sorting ints with Bubblesort\n";

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

cout << array[i] << '\n';

 Bubblesort((byte*)array, 5, sizeof(array[0]), &CompareInts);

 cout << "After the sorting\n";

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

cout << array[i] << '\n';

 const char str[5][10] = {"estella","danielle","crissy","bo","angie"};

 cout << "Before sorting strings with Quicksort\n";

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

cout << str[i] << '\n';

 Quicksort((byte*)str, 5, 10, &CompareStrings);

 cout << "After the sorting\n";

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

cout << str[i] << '\n';

 return 0;

}

如果想进行降序排序(大元素在先),就只需修改回调函数的代码,或使用另一个回调函数,这样编程起来灵活性就比较大了。

调用约定

上面的代码中,可在函数原型中找到__stdcall,因为它以双下划线打头,所以它是一个特定于编译器的扩展,说到底也就是微软的实现。任何支持开发基于Win32的程序都必须支持这个扩展或其等价物。以__stdcall标识的函数使用了标准调用约定,为什么叫标准约定呢,因为所有的Win32 API(除了个别接受可变参数的除外)都使用它。标准调用约定的函数在它们返回到调用者之前,都会从堆栈中移除掉参数,这也是Pascal的标准约定。但在C/C++中,调用约定是调用者负责清理堆栈,而不是被调用函数;为强制函数使用C/C++调用约定,可使用__cdecl。另外,可变参数函数也使用C/C++调用约定。

Windows操作系统采用了标准调用约定(Pascal约定),因为其可减小代码的体积。这点对早期的Windows来说非常重要,因为那时它运行在只有640KB内存的电脑上。

如果你不喜欢__stdcall,还可以使用CALLBACK宏,它定义在windef.h中:

#define CALLBACK __stdcallor

#define CALLBACK PASCAL //而PASCAL在此被#defined成__stdcall

作为回调函数的C++方法

因为平时很可能会使用到C++编写代码,也许会想到把回调函数写成类中的一个方法,但先来看看以下的代码:

class CCallbackTester

{

 public:

 int CALLBACK CompareInts(const byte* velem1, const byte* velem2);

};

Bubblesort((byte*)array, 5, sizeof(array[0]),

&CCallbackTester::CompareInts);

如果使用微软的编译器,将会得到下面这个编译错误:

error C2664: 'Bubblesort' : cannot convert parameter 4 from

'int (__stdcall CCallbackTester::*)(const unsigned char *,

const unsigned char *)' to 'int (__stdcall *)(const unsigned char *,

const unsigned char *)' There is no context in which this conversion is possible

这是因为非静态成员函数有一个额外的参数:this指针,这将迫使你在成员函数前面加上static。当然,还有几种方法可以解决这个问题,但限于篇幅,就不再论述了。

查看本文来源

    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章