C++ 回调函数学习笔记(从入门到理解)
一、什么是回调函数Callback1. 一句话理解把一个函数“交给别人”在合适的时候由别人调用这就是回调。你写函数不自己主动调而是让别人帮你在某个时机执行。二、生活中的理解外卖例子你点外卖时你对平台说到了给我打电话。这个“打电话”动作就是你提供的回调函数。你不需要一直问外卖到了没外卖到了平台会主动调用你留的“通知函数”三、本质定义回调 函数指针 / 可调用对象被其他函数调用公式把函数A作为参数 传给函数B 由函数B在某个时机调用函数AA回调函数B触发回调的函数四、最基础回调函数指针示例1#include iostream using namespace std; void hello() { cout 我是回调函数 endl; } void execute(void (*cb)()) { cout 先做自己的事... endl; cb(); // 调用回调 } int main() { execute(hello); }输出先做自己的事... 我是回调函数分析这个void (*cb)()是函数指针。意思cb 是一个指针 指向参数为空 返回void的函数拆开理解普通函数void hello();函数指针void (*p)();赋值p hello;调用p();图解hello --- 函数地址 ↓ p ↓ p();五、带参数回调#include iostream using namespace std; void printSum(int a,int b) { coutabendl; } void calc(void (*cb)(int,int)) { cb(3,5); } int main() { calc(printSum); }输8六、为什么需要回调不用回调任务完成 然后自己主动去检查轮询低效用回调任务完成 系统自动通知你事件驱动高效常见场景按钮点击Qtconnect(button, QPushButton::clicked, this, MainWindow::onClick);点击按钮onClick()就是回调。七、C风格回调函数指针经典写法void doWork(void (*callback)()) //void (*callback)()是一个函数函数指针 { //任务完成 callback(); }优点快简单缺点只能传普通函数不灵活八、C现代回调 std::function这个比函数指针高级很多。头文件#include functional写法functionvoid()意思返回 void 参数为空 可调用对象示例#include iostream #include functional using namespace std; void test() { couthelloendl; } void run(functionvoid() cb) { cb(); } int main() { run(test); }和函数指针对比函数指针void (*cb)()现代写法functionvoid() cb更像装任何能调用的东西的容器九、function 能装什么1 普通函数run(test);2 Lambdarun([](){ coutlambda; });3 仿函数class Functor { public: void operator()() { cout仿函数; } }; run(Functor());三者都能回调普通函数 Lambda 函数对象这就是现代 C 强大之处。十、Lambda做回调最常用#include iostream using namespace std; void work(functionvoid() cb) { cout处理中...endl; cb(); } int main() { work([](){ cout处理完成; }); }输出处理中... 处理完成十一、带状态的回调函数指针做不到我要回调还能带变量Lambda可以int x10; auto cb[x]() { coutx; };输出10这叫捕获变量十二、异步回调思想下载文件 下载完通知我伪代码download(url, [](){ cout下载完成; });是不是很像事件发生 触发回调十三、回调本质图你写函数 ↓ 交给系统 ↓ 事件发生 ↓ 系统调用你的函数就是回调。十四、回调 vs 普通函数调用普通调用main └── hello()你主动调。回调main └── system └── hello()系统替你调。十五、回调常见面试题Q1 什么是回调答将函数作为参数传递 由其他函数在特定时机调用Q2 回调实现方式函数指针std::functionlambda仿函数成员函数绑定Q3 函数指针和function区别对比函数指针std::function普通函数支持支持lambda有限支持仿函数不方便支持灵活性低高现代C较少常用结论现代开发优先 std::function十六、手写一个回调框架#include iostream #include functional using namespace std; class Task { private: functionvoid() callback; public: void setCallback(functionvoid() cb) { callbackcb; } void run() { cout任务执行中...endl; if(callback) callback(); } }; int main() { Task t; t.setCallback([](){ cout任务完成回调; }); t.run(); }输出任务执行中... 任务完成回调十八、记忆口诀自己调用叫函数调用 别人调用叫回调十九、⭐核心代码模板⭐传统函数指针模板void callback() { } void run(void (*cb)()) { cb(); } int main() { run(callback); }现代模板#include functional using namespace std; void run(functionvoid() cb) { cb(); } int main() { run([](){ }); }二十、容易混淆的几个概念回调 vs 函数指针不是一个东西。函数指针只是实现回调的一种方式回调 vs LambdaLambda不是回调。Lambda可以作为回调回调 vs 异步不是一回事异步常用回调通知结果回调不一定异步二十一、总结回调本质把函数交出去 让别人以后调用实现方式函数指针 std::function lambda 仿函数现代推荐std::function lambda二十二、最后一句理解回调不是我去调用函数 而是我把函数留给系统 等系统回来调用我这就是回调。