C++ 回调函数学习笔记(从入门到理解)
2026/4/30 14:23:28 网站建设 项目流程

一、什么是回调函数(Callback)

1. 一句话理解

把一个函数“交给别人”,在合适的时候由别人调用,这就是回调。

你写函数,不自己主动调,而是让别人帮你在某个时机执行。


二、生活中的理解

外卖例子

你点外卖时:

你对平台说:

到了给我打电话。

这个“打电话”动作就是你提供的回调函数

  • 你不需要一直问外卖到了没

  • 外卖到了平台会主动调用你留的“通知函数”


三、本质定义

回调 =函数指针 / 可调用对象+被其他函数调用

公式:

把函数A作为参数 传给函数B 由函数B在某个时机调用函数A

A:回调函数
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) { cout<<a+b<<endl; } void calc(void (*cb)(int,int)) { cb(3,5); } int main() { calc(printSum); }

8

六、为什么需要回调

不用回调

任务完成 然后自己主动去检查

轮询(低效)


用回调

任务完成 系统自动通知你

事件驱动(高效)


常见场景

按钮点击

Qt:

connect(button, &QPushButton::clicked, this, &MainWindow::onClick);

点击按钮:

onClick()

就是回调。


七、C风格回调(函数指针)

经典写法:

void doWork(void (*callback)()) //void (*callback)()是一个函数函数指针 { //任务完成 callback(); }

优点:

  • 简单

缺点:

  • 只能传普通函数

  • 不灵活


八、C++现代回调 std::function

这个比函数指针高级很多。


头文件

#include <functional>

写法

function<void()>

意思:

返回 void 参数为空 可调用对象

示例

#include <iostream> #include <functional> using namespace std; void test() { cout<<"hello"<<endl; } void run(function<void()> cb) { cb(); } int main() { run(test); }

和函数指针对比

函数指针:

void (*cb)()

现代写法:

function<void()> cb

更像:

装任何能调用的东西的容器

九、function 能装什么


1 普通函数

run(test);

2 Lambda

run([](){ cout<<"lambda"; });

3 仿函数

class Functor { public: void operator()() { cout<<"仿函数"; } }; run(Functor());

三者都能回调

普通函数 Lambda 函数对象

这就是现代 C++ 强大之处。


十、Lambda做回调(最常用)

#include <iostream> using namespace std; void work(function<void()> cb) { cout<<"处理中..."<<endl; cb(); } int main() { work([](){ cout<<"处理完成"; }); }

输出

处理中... 处理完成

十一、带状态的回调

函数指针做不到:

我要回调还能带变量

Lambda可以:

int x=10; auto cb=[x]() { cout<<x; };

输出

10

这叫:捕获变量


十二、异步回调思想

下载文件 下载完通知我

伪代码:

download(url, [](){ cout<<"下载完成"; });

是不是很像:

事件发生 触发回调

十三、回调本质图

你写函数 ↓ 交给系统 ↓ 事件发生 ↓ 系统调用你的函数

就是回调。


十四、回调 vs 普通函数调用

普通调用

main └── hello()

你主动调。


回调

main └── system └── hello()

系统替你调。


十五、回调常见面试题


Q1 什么是回调

答:

将函数作为参数传递 由其他函数在特定时机调用

Q2 回调实现方式

  • 函数指针

  • std::function

  • lambda

  • 仿函数

  • 成员函数绑定


Q3 函数指针和function区别

对比函数指针std::function
普通函数支持支持
lambda有限支持
仿函数不方便支持
灵活性
现代C++较少常用

结论:

现代开发优先 std::function

十六、手写一个回调框架

#include <iostream> #include <functional> using namespace std; class Task { private: function<void()> callback; public: void setCallback(function<void()> cb) { callback=cb; } 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(function<void()> cb) { cb(); } int main() { run([](){ }); }

二十、容易混淆的几个概念

回调 vs 函数指针

不是一个东西。

函数指针只是:

实现回调的一种方式

回调 vs Lambda

Lambda不是回调。

Lambda可以作为回调

回调 vs 异步

不是一回事:

  • 异步常用回调通知结果

  • 回调不一定异步


二十一、总结

回调本质

把函数交出去 让别人以后调用

实现方式

函数指针 std::function lambda 仿函数

现代推荐:

std::function + lambda

二十二、最后一句理解回调

不是我去调用函数 而是我把函数留给系统 等系统回来调用我

这就是回调。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询