C++的回调函数

一、简介

本文主要介绍C++中如何使用回调函数。

二、回调函数介绍

回调函数主要在“回”字,和正常的函数调用方式不太一样。正常的函数由开发者自己定义返回类型以及传入的参数,并且也是由开发者自己调用,而回调函数功能其实也是由开发者自己实现,但是返回类型以及入参则由注册回调的函数来决定(若是自己编写则可以自定义注册函数,由他人提供则只能根据接口实现),而且调用方也不是开发者,而是注册方决定。

整个过程也就是一个“回”字,开发者将自己的函数指针交给对方,这是“去”,而对方则在适当的时候调用这个函数,也可以将一些开发者需要的数据传回来,这便是来回了。

总而言之,正常情况是开发者调用API,调用权在开发者手中,而回调函数则相当于API调用开发者提供的函数,主被动转换了。

三、回调函数用处

那么,回调函数的用处是什么呢?既然发明了回调函数,自然是有其用武之地了。

如果你对上面的解释比较理解的话,你就会发现回调函数真的用的很多,比如事件,其底层就是回调函数,比如最简单的UI窗口鼠标点击事件,是否是由开发者编写函数具体实现,而调用的时机是由UI框架决定呢?不过很多开发者可能由于框架封装的十分简单易用,所以没有察觉到。

四、回调函数示例

了解了概念后,我们自然是要学习如何自己实现回调函数的注册了。本文以C++为例。
void sample(void (*callback)()){callback();}

void callbackFun1(){std::cout << "call the function1" << std::endl;}

void callbackFun2(){std::cout << "call the function2" << std::endl;}

int main(){sample(callbackFun1);sample(callbackFun2);std::system("pause");

return 0;}
C++的回调函数

如上所示,这便是最简单的回调函数了。

sample函数的入参为void (callback) (),共有三部分,void 表示返回类型,(callback)为函数指针,() 则代表回调函数的入参,此处无入参。

因此只要是返回类型为void,参数为空的函数,sample都能够调用。

一般为了方便调用,都会使用typedef,如下。

typedef int (*myFun) (int&, int);

int sample(myFun mF, int& a, int b)
{
    b = 2;
    return mF(a, b);
}

int callbackFun1(int& a, int b)
{
    a++;
    return a+b;
}

int main()
{
    int a = 0;
    int b = 1;
    int c = sample(callbackFun1, a, b);

    std::cout << "a = " << a << "  b = " << b << "  c = " << c << std::endl;

    std::system("pause");

    return 0;
}

C++的回调函数

结果是否和你计算的一样呢?

以上都是直接触发,但是大部分框架可就复杂多了,可不是这么简单的调用,只会在需要的时候才会触发!

typedef int (*myFun) (int&, int);

struct fun
{
    myFun mF;
    int a;
    int b;

    fun(myFun _mF, int _a, int _b)
    {
        mF = _mF;
        a = _a;
        b = _b;
    }
};

std::vector<fun> funs;

void regisiterCallback(myFun mF, int& a, int b)
{
    funs.emplace_back(fun(mF, a, b));
}

int callbackFun1(int& a, int b)
{
    return a+b;
}

int main()
{
    int a = 0;
    int b = 0;
    regisiterCallback(callbackFun1, a, b);

    a++;
    b++;
    regisiterCallback(callbackFun1, a, b);

    std::cout << funs[1].mF(funs[1].a, funs[1].b) << std::endl;
    std::cout << funs[0].mF(funs[0].a, funs[0].b) << std::endl;

    std::system("pause");

    return 0;
}

C++的回调函数

如上regisiter函数只是负责注册回调,并没有触发回调函数,在main中才真正调用,并且我特意先调用了第二个注册的回调,结果也是先输出了第二个注册的回调,因此回调函数的调用先后顺序与注册顺序没有关系,只跟注册方实际调用顺序有关。

五、总结

本文内容为我个人之谈,如有错误,欢迎指正!
原文链接: https://www.cnblogs.com/Clark-Zhang/p/16687560.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/5644

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年2月4日 下午7:45
下一篇 2023年2月4日 下午7:46

相关推荐