C++回调函数以及使用方法
·
一、回调函数的概念
把一个函数的“地址”或“可调用对象”作为参数传递给另一个函数,当这个函数执行到某个特定时机时,再“回过头”调用你提供的函数。
#include <iostream>
using namespace std;
// 回调函数类型:接收一个整数参数的函数
void myCallback(int value) {
cout << "Callback called! Value = " << value << endl;
}
// 普通函数,接受一个函数指针作为参数
void processData(int data, void (*callback)(int)) {
cout << "Processing data..." << endl;
data += 10;
// 在特定时刻调用回调
callback(data);
}
int main() {
processData(5, myCallback);
return 0;
}
输出:
Processing data...
Callback called! Value = 15
• processData 是框架或底层库;
• myCallback 是上层逻辑;
• 你传给别人一个函数指针,别人异步或延迟地再调用回来。
二、C++中几种实现回调的方法
1、传统函数指针
void doSomething(void (*callback)(int));
缺点:类型受限、无法绑定对象、无法捕获上下文。
2、std::function + std::bind(现代 C++ 推荐)
#include <iostream>
#include <functional>
using namespace std;
void doTask(int x, std::function<void(int)> callback) {
cout << "Working..." << endl;
callback(x + 10);
}
class Worker {
public:
void onFinish(int result) {
cout << "Task finished with result: " << result << endl;
}
};
int main() {
Worker w;
// 可以绑定成员函数
doTask(5, std::bind(&Worker::onFinish, &w, std::placeholders::_1));
// 或直接用lambda
doTask(10, [](int val) {
cout << "Lambda callback result: " << val << endl;
});
}
• 支持成员函数、lambda、自由函数;
• 支持捕获外部变量;
• 语法更安全、更灵活;
• 现代C++推荐使用。
3、Lambda表达式作为回调
auto callback = [](int result) {
std::cout << "Callback result: " << result << std::endl;
};
doTask(42, callback);
//可以直接捕获变量,非常方便:
int base = 100;
doTask(10, [base](int result) {
std::cout << "Result + base = " << result + base << std::endl;
});
三、回调函数的典型实用场景
1、异步任务完成通知
void downloadFile(const std::string &url, std::function<void(bool)> onComplete);
当下载完成后自动回调 onComplete(true) 或 onComplete(false)。
2、事件驱动
class Button {
public:
std::function<void()> onClick;
void click() {
if (onClick) onClick();
}
};
int main() {
Button btn;
btn.onClick = [](){ std::cout << "Button clicked!" << std::endl; };
btn.click();
}
模仿了 Qt 的 connect(button, &QPushButton::clicked, ...)。
3、插件系统或策略模式
//通过回调或注册函数实现动态行为切换。
class Logger {
public:
std::function<void(const std::string&)> output;
void log(const std::string& msg) {
if (output)
output("[LOG] " + msg);
}
};
int main() {
Logger logger;
// 控制台输出
logger.output = [](const std::string& msg){ std::cout << msg << std::endl; };
// 文件输出
// logger.output = [](const std::string& msg){ writeToFile(msg); };
logger.log("System started");
}
四、在实际项目中的设计模式与回调结合
| 场景 | 典型实使用方法 |
|---|---|
| 网络通信 | 异步connect成功/失败---->回调 |
| 文件下载 | 进度、完成回调 |
| 线程池 | 任务结束--->回调通知UI |
| 自定义控件 | 用户点击、输入--->回调 |
| 插件架构 | 注册接口回调函数 |
| 定时任务 | 到时间调用注册回调 |
五、最佳实践
1. 优先使用 std::function 取代原始函数指针
• 更安全,可存储 lambda、成员函数。
2. 命名规范
• 一般命名为 onXxx 或 callbackXxx。
std::function<void(int)> onProgress;
std::function<void()> onFinish;
3. 调用前判断是否为空
if (onFinish) onFinish();
4.生命周期管理
•注意:如果对象在回调执行前被销毁,可能导致悬空指针;
•常用方法:使用 std::weak_ptr 或 QObject::deleteLater。
六、真实案例(下载器场景)
#include <iostream>
#include <thread>
#include <functional>
#include <chrono>
using namespace std;
class Downloader {
public:
std::function<void(int)> onProgress;
std::function<void()> onFinish;
void start() {
std::thread([this]() {
for (int i = 0; i <= 100; i += 20) {
std::this_thread::sleep_for(std::chrono::milliseconds(300));
if (onProgress) onProgress(i);
}
if (onFinish) onFinish();
}).detach();
}
};
int main() {
Downloader d;
d.onProgress = [](int p){ cout << "Progress: " << p << "%" << endl; };
d.onFinish = [](){ cout << "Download complete!" << endl; };
d.start();
std::this_thread::sleep_for(std::chrono::seconds(2));
}
输出:
Progress: 0%
Progress: 20%
Progress: 40%
Progress: 60%
Progress: 80%
Progress: 100%
Download complete!
更多推荐

所有评论(0)