首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C++ >

《小弟我的第一本C++书》节选:11.1.3 用函数指针实现回调函数

2014-01-05 
《我的第一本C++书》节选:11.1.3用函数指针实现回调函数11.1.3用函数指针实现回调函数除了可以使用函数指针

《我的第一本C++书》节选:11.1.3 用函数指针实现回调函数

11.1.3  用函数指针实现回调函数

除了可以使用函数指针简化函数的调用之外,函数指针更大的用途在于它可以作为函数参数传递给某个函数,从而实现函数的回调。所谓函数的回调,就是在某个函数中,通过函数指针调用另外一个函数,而这个函数指针,大多数情况下是通过函数参数传递进来的。如果把函数的指针作为参数传递给另一个函数,那么当这个函数指针用于调用它所指向的函数时,就说这个函数是回调函数。 函数指针已经够复杂了,为什么还要使用它来作为函数参数进行函数的回调?程序简单一点不是更好吗? 回调函数的使用,正是为了让程序变得更简单。因为回调函数可以把主调函数与被调函数分开,主调函数不必关心谁是被调函数,所有它需要知道的只是存在一个具有某种特定原型、某些限制条件的被调函数。这就像在主调函数中留下了一个插口,它定义了插口的规则,也就是函数的返回值和具体的参数。而被调函数就是插头,可以把任何符合这个插口规则的插头插入这个插口中,从而实现整个主调函数。也可以通过改变插入的插头来改变主调函数的功能,从而改变主调函数的实现。使用回调函数可以实现同一个算法框架、不同的算法实现,最终达到算法的通用。 还是回到上面的例子,看看如何使用回调函数让程序更具灵活性、更加通用。假设现在要求在每条打印消息的前后还要打印一些符号作为装饰,为了完成这项任务,可以定义一个统一的打印消息函数。
 

// 定义函数指针类型
typedef void (* PRINTFUNC )(int);
// 统一的打印消息函数
void PrintMessage( int nSocre , PRINTFUNC pFunc )
{
    cout<<"============"<<endl;
    // 通过函数指针回调函数
    (*pFunc)(nSocre);
    cout<<"++++++++++++"<<endl;
}
// 主函数
int _tmain(int argc, _TCHAR* argv[])
{
    int nScore = 22;
 
    PRINTFUNC pFunc;
    // 根据不同分数给pFunc赋值
    // …
 
    // 使用不同函数指针作为参数调用PrintMessage()函数
    PrintMessage( nScore, pFunc );
 
    return 0;
}

在这里,实际上是通过PrintMessage()函数定义了一个通用算法框架:首先打印页眉;然后通过函数指针回调函数,打印具体的消息;最后打印页脚。PrintMessage()函数只完成最基本的页眉、页脚的打印,至于具体的消息,则留给回调函数负责,这就像留下一个插口,等待某个具体的回调函数插头的插入。在主函数中,通过给PrintMessage()函数传递不同的打印函数的指针,就如同将某个插头插入PrintMessage()函数所留下的插口中。不同函数指针插头的插入,可以改变PrintMessage()函数中的回调函数,进而改变PrintMessage()函数的行为,以达到对其行为进行自定义的效果。回调函数与插头理论的关系如图11-1所示。

clip_image002

通过回调函数改变一个函数的行为、对其行为进行自定义的特性被广泛应用在通用算法的设计中。假设有这样一种情况,要编写一个库,它提供了某些排序算法的实现,如冒泡排序、快速排序等,为了使库更加通用,不想在函数中嵌入排序逻辑,而让使用者来实现具体的排序逻辑,或者让库用于多种数据类型。这时,回调函数就可以派上用场了。可以在通用算法中定义好算法的框架,至于其中核心的算法逻辑,则留待回调函数去完成。用户可以通过不同的回调函数,轻松简单地实现各种算法,对算法进行自定义。

热点排行