案例3:带用户数据的回调函数 在实际应用中,我们经常需要给回调函数传递额外的上下文数据。下面看看几种实现方式: 使用 void 指针传递用户数据(C语言风格)// 用户数据结构体
struct UserData {
constchar* name;
int id;
};
// 回调函数类型
typedef void (*Callback)(int result, void* userData);
// 实际的回调函数
void processResult(int result, void* userData) {
UserData* data = (UserData*)userData;
printf("用户 %s (ID: %d) 收到结果: %d\n",
data->name, data->id, result);
}
// 执行任务的函数
void executeTask(Callback callback, void* userData) {
int result = 100;
callback(result, userData);
}
int main() {
// 创建用户数据
UserData user = {"张三", 1001};
// 执行任务
executeTask(processResult, &user);
return0;
}
这种方式通过void*类型参数传递任意类型的数据,是C语言中最常见的方式。但缺点是缺乏类型安全性,容易出错。 使用C++11的 std::function 和 lambda 表达式// 使用std::function定义回调类型
using TaskCallback = std::function<void(int)>;
// 执行任务的函数
void executeTask(TaskCallback callback) {
int result = 300;
callback(result);
}
int main() {
// 使用lambda捕获局部变量
std::string userName = "用户1";
int userId = 2001;
// lambda捕获外部变量
executeTask([userName, userId](int result) {
std::cout << userName << " (ID: " << userId
<< ") 收到结果: " << result << std::endl;
});
return0;
}
这种方式最灵活,lambda表达式可以直接捕获周围环境中的变量,大大简化了代码。
七、回调函数的设计模式 回调函数在各种设计模式中广泛应用,下面介绍两个常见的模式: 1. 观察者模式(Observer Pattern)观察者模式中,多个观察者注册到被观察对象,当被观察对象状态变化时,通知所有观察者: // 使用C++11的方式实现观察者模式
class Subject {
private:
// 存储观察者的回调函数
std::vector<std::function<void(conststd::string&)>> observers;
public:
// 添加观察者
void addObserver(std::function<void(const std::string&)> observer) {
observers.push_back(observer);
}
// 通知所有观察者
void notifyObservers(const std::string& message) {
for (auto& observer : observers) {
observer(message);
}
}
};
这个模式在GUI编程、消息系统、事件处理中非常常见。 2. 策略模式(Strategy Pattern)策略模式使用回调函数实现不同的算法策略: // 定义策略类型(使用回调函数)
using SortStrategy = std::function<void(std::vector<int>&)>;
// 排序上下文类
class Sorter {
private:
SortStrategy strategy;
public:
Sorter(SortStrategy strategy) : strategy(strategy) {}
void setStrategy(SortStrategy newStrategy) {
strategy = newStrategy;
}
void sort(std::vector<int>& data) {
strategy(data);
}
};
策略模式允许在运行时切换算法,非常灵活。
|