回调函数的基本概念
回调函数的本质是"你定义,我调用" - 你提供一个函数,系统或框架在特定时机调用它。
实现回调函数的几种方式
1. 函数指针(传统方式)
#include <iostream>
// 回调函数类型定义
typedef void (*Callback)(int, const std::string&);
// 接受回调函数的函数
void processData(int value, const std::string& name, Callback callback) {
std::cout << "处理数据中..." << std::endl;
// 处理完成后调用回调函数
callback(value, name);
}
// 具体的回调函数实现
void myCallback(int num, const std::string& text) {
std::cout << "回调函数被调用: " << num << ", " << text << std::endl;
}
int main() {
processData(42, "Hello", myCallback);
return 0;
}
2. std::function(现代方式)
#include <iostream>
#include <functional>
void processData(int value, const std::string& name,
std::function<void(int, const std::string&)> callback) {
std::cout << "处理数据中..." << std::endl;
callback(value, name);
}
void myCallback(int num, const std::string& text) {
std::cout << "回调函数被调用: " << num << ", " << text << std::endl;
}
int main() {
// 使用函数指针
processData(42, "World", myCallback);
// 使用lambda表达式
processData(100, "Lambda", [](int n, const std::string& s) {
std::cout << "Lambda回调: " << n << ", " << s << std::endl;
});
return 0;
}
3. 函数对象(Functor)
#include <iostream>
class MyCallback {
public:
void operator()(int value, const std::string& message) {
std::cout << "函数对象回调: " << value << ", " << message << std::endl;
}
};
template<typename CallbackType>
void processData(int value, const std::string& name, CallbackType callback) {
std::cout << "处理数据中..." << std::endl;
callback(value, name);
}
int main() {
MyCallback callbackObj;
processData(200, "Functor", callbackObj);
return 0;
}
实际应用示例
事件处理系统
#include <iostream>
#include <functional>
#include <vector>
class Button {
private:
std::vector<std::function<void()>> clickCallbacks;
public:
// 注册点击回调
void onClick(std::function<void()> callback) {
clickCallbacks.push_back(callback);
}
// 模拟按钮点击
void click() {
std::cout << "按钮被点击!" << std::endl;
for (auto& callback : clickCallbacks) {
callback();
}
}
};
int main() {
Button btn;
// 注册多个回调函数
btn.onClick([]() {
std::cout << "执行操作1: 保存文件" << std::endl;
});
btn.onClick([]() {
std::cout << "执行操作2: 更新界面" << std::endl;
});
// 模拟点击
btn.click();
return 0;
}
异步操作回调
#include <iostream>
#include <functional>
#include <thread>
#include <chrono>
void asyncOperation(std::function<void(bool, const std::string&)> callback) {
std::thread([callback]() {
std::cout << "开始异步操作..." << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(2));
// 模拟操作完成
bool success = true; // 或 false
std::string result = "操作完成";
callback(success, result);
}).detach();
}
int main() {
std::cout << "主线程继续执行..." << std::endl;
asyncOperation([](bool success, const std::string& message) {
if (success) {
std::cout << "成功: " << message << std::endl;
} else {
std::cout << "失败: " << message << std::endl;
}
});
// 等待异步操作完成
std::this_thread::sleep_for(std::chrono::seconds(3));
return 0;
}
回调函数的优点
-
灵活性: 可以在运行时决定执行什么代码
-
解耦合: 将调用者和被调用者分离
-
可扩展性: 容易添加新的回调函数
-
异步支持: 非常适合异步编程模式
注意事项
-
使用
std::function比原始函数指针更安全灵活 -
注意回调函数的生命周期管理
-
在多线程环境中要注意线程安全问题
-
避免过深的回调嵌套(回调地狱)
回调函数是C++中实现事件驱动编程和异步编程的重要工具,在现代C++开发中广泛应用。