码农知识堂 - 1000bd
  •   Python
  •   PHP
  •   JS/TS
  •   JAVA
  •   C/C++
  •   C#
  •   GO
  •   Kotlin
  •   Swift
  • c++回调函数详解及实现(lambda)


    回调函数就是一个被作为参数传递的函数。在C语言中,回调函数只能使用函数指针实现,在C++语言中还可以使用仿函数或匿名函数。回调函数的使用可以大大提升编程的效率,这使得它在现代编程中被非常多地使用。

    回调的好处

    用于解耦,可以把调用者与被调用者分开,所以调用者不关心谁是被调用者。它只需知道存在一个具有特定原型和限制条件的被调用函数。简而言之,回调函数就是允许用户把需要调用的函数的指针作为参数传递给一个函数,以便该函数在处理相似事件的时候可以灵活的使用不同的方法。

    回调还可用于通知机制。当某一事件发生时,如果使用者注册过了回调函数,则会自动执行回调函数中的内容。

    回调还可用于预留逻辑,比如当时不确定或者根本不确定某一条件下要执行什么操作,就把选择权留给使用者,让使用者来实现相应的逻辑。比如某些函数库,排序算法的实现,为了能让库更加通用,不想在函数中嵌入排序逻辑,而让使用者来实现相应的逻辑。

    比如应用开发者和内核之间,应用者注册了信号处理,实则就是一种回调注册。

    如下图所示:

     

    回调的使用

    ⑴定义一个回调函数。

    ⑵提供函数实现的一方在初始化的时候,将回调函数的函数指针注册给调用者。

    ⑶当特定的事件或条件发生的时候,调用者使永函数指针调用回调函数对事件进行处理。

    c++回调的实现

    网上的例子大多太旧,没有用到现代c++的特性,还是以往函数指针的实现。

    以下示例为使用现在c++14以上实现,包括lambda表达式的使用。

    1. #include
    2. #include
    3. class MyTest{
    4. public:
    5. MyTest() = default;
    6. void doCalc(){
    7. //干其他事,完了
    8. // 执行回调
    9. if(myCallBack!= nullptr){
    10. myCallBack(1,2);
    11. }
    12. }
    13. using callback_t = std::function<void(const int &a, const int &b)>;
    14. // 注册回调
    15. void setCallBackHandler(const callback_t &cb){
    16. myCallBack = cb;
    17. }
    18. private:
    19. // 定义回调
    20. callback_t myCallBack;
    21. };
    22. // 回调函数
    23. void handleCallBack(const int &a,const int &b){
    24. std::cout << "this is from callback handleCallBack"<
    25. }
    26. int main(){
    27. MyTest t;
    28. // 回调函数
    29. auto f= [](const int &a,const int &b){
    30. std::cout << "this is from callback f"<
    31. };
    32. // 注册回调
    33. // 写法一
    34. t.setCallBackHandler(f);
    35. // 写法二
    36. t.setCallBackHandler([&f](auto &&a, auto &&b) {
    37. f(std::forward<decltype(a)>(a), std::forward<decltype(b)>(b));
    38. });
    39. // 写法三
    40. t.setCallBackHandler([](auto &&a, auto &&b) {
    41. handleCallBack(std::forward<decltype(a)>(a), std::forward<decltype(b)>(b));
    42. });
    43. t.doCalc();
    44. }

    以上对形参使用了类似如auto的写法,这是c++14的特性。

    至于参数为啥要用&&?是为了做到完美转发。要做到这一点,参数 必须成为通用引用(见条款 24)。

    条款 33:对 auto&&形参使用 decltype 来 std::forward。
    C++14 最令人兴奋的特性之一是在参数规范中使用 auto 的泛型 lambda。 

    在 lambda 中,我们可以通过检查的参数 x 的类型,来判断实参是左值还是右值。

    条款 28 解释到,如果将左值实参传递给通用引用,该参数的类型将成为左值引用,如果传递的是右值,该参数将成为一个右值引用。这意味着,在 lambda 中,我们可以通过检查的参数 x 的类型,来判断实参是左值还是右值。

    decltype(见条款 3)给了我们一个实现途径。如果是左值,decltype(x)得到的类型是左值引用,如果是右值,decltype(x)得到的是右值引用。

    需要铭记的是:对 auto&&形参使用 decltype 来 std::forward。

    以上条款详细内容参见《Effective.Modern.C++》一书。

    c语言的实现

    1. #include
    2. #include
    3. #include
    4. typedef int (callBack)(const void *buffer,size_t size,char *p_out);
    5. void callFunc(callBack *my_callback, char *p_out) {
    6. printf("callFunc\n");
    7. const void *buffer = NULL;
    8. my_callback(buffer,0,p_out); //传入值可以随便填
    9. }
    10. int callBackFunc(const void *buffer, size_t size, char *p_out){
    11. printf("callBackFunc\n");
    12. memset(p_out,0x00,sizeof(char)*100);
    13. strcpy(p_out,"this is Callback:this is string.");
    14. return 1;
    15. }
    16. int main(int argc,char *args[]){
    17. char p_out[100];
    18. callFunc(callBackFunc,p_out);
    19. printf("%s\n",p_out);
    20. return 0;
    21. }

    引用

    什么是回调函数?为什么要使用回调函数?如何使用回调函数?_llzhang_fly的博客-CSDN博客_回调函数

    C++回调函数的基本理解和使用_一度凡尘的博客-CSDN博客_回调函数 

    回调函数的实质——什么是回调函数,为什么要使用回调函数_斗趣的博客-CSDN博客_回调函数

    c++11线程池的实现原理及回调函数的使用_特立独行的猫a的博客-CSDN博客_c++多线程回调函数 深入理解:回调函数_极客点儿的博客-CSDN博客_回调函数

    C++学习之回调函数_欧特克_Glodon的博客-CSDN博客 

    关于C++ 回调函数(callback) 精简且实用_zhoupian的博客-CSDN博客_c++ callback

  • 相关阅读:
    第十一届蓝桥杯省赛第一场C++ B组《整除序列》(c++)
    Gradle 出现 Could not resolve gradle
    word图片的标题跑到了图片的上方。
    TL,你是如何管理项目风险的?
    前端大容量存储方案IndexedDB
    浅析vue3PDF插件不显示文字
    私藏!资深数据专家SQL效率优化技巧
    【广度优先搜索】leetcode 542. 01 矩阵
    【气动学】基于Matlab模拟各类导弹跟踪
    优化Java虚拟机参数
  • 原文地址:https://blog.csdn.net/qq8864/article/details/126442128
  • 最新文章
  • 攻防演习之三天拿下官网站群
    数据安全治理学习——前期安全规划和安全管理体系建设
    企业安全 | 企业内一次钓鱼演练准备过程
    内网渗透测试 | Kerberos协议及其部分攻击手法
    0day的产生 | 不懂代码的"代码审计"
    安装scrcpy-client模块av模块异常,环境问题解决方案
    leetcode hot100【LeetCode 279. 完全平方数】java实现
    OpenWrt下安装Mosquitto
    AnatoMask论文汇总
    【AI日记】24.11.01 LangChain、openai api和github copilot
  • 热门文章
  • 十款代码表白小特效 一个比一个浪漫 赶紧收藏起来吧!!!
    奉劝各位学弟学妹们,该打造你的技术影响力了!
    五年了,我在 CSDN 的两个一百万。
    Java俄罗斯方块,老程序员花了一个周末,连接中学年代!
    面试官都震惊,你这网络基础可以啊!
    你真的会用百度吗?我不信 — 那些不为人知的搜索引擎语法
    心情不好的时候,用 Python 画棵樱花树送给自己吧
    通宵一晚做出来的一款类似CS的第一人称射击游戏Demo!原来做游戏也不是很难,连憨憨学妹都学会了!
    13 万字 C 语言从入门到精通保姆级教程2021 年版
    10行代码集2000张美女图,Python爬虫120例,再上征途
Copyright © 2022 侵权请联系2656653265@qq.com    京ICP备2022015340号-1
正则表达式工具 cron表达式工具 密码生成工具

京公网安备 11010502049817号