【C++】回调函数
前言
学习回调函数,回调函数是通过函数指针或对象调用的函数。
回调函数就是通过函数指针或对象调用的函数,只要能一个函数能够作为参数传入并调用,这个函数就是回调函数。
#include <iostream>
int addCallBack(int a,int b){//回调函数
std::cout <<a+b<<std::endl;
return 0;
}
int main(int argc, char** argv) {
int(*p)(int,int);
p = addCallBack;
p(1,2);
return 0;
}
为什么使用回调函数
前言里直接在main函数调用addCallBack不是更直接吗?为什么要使用函数指针接收addCallBack的地址,再调用呢?
回调函数,通常是为了实现“控制反转”(Inversion of Control), 灵活、分离、 异步与并发。
- 解耦和模块化: 函数与具体的逻辑解耦,可以复用。
// 排序算法(不关心具体比较逻辑)
void sort(int* arr, int n, bool(*compare)(int, int)) {
for (int i = 0; i < n-1; i++) { //解耦和模块化
for (int j = i+1; j < n; j++) {
if (compare(arr[i], arr[j])) {
std::swap(arr[i], arr[j]);
}
}
}
}
// 不同的比较策略
bool ascending(int a, int b) { return a > b; }
bool descending(int a, int b) { return a < b; }
int main() {
int data[] = {5, 2, 8, 1, 3};
sort(data, 5, ascending); // 升序
sort(data, 5, descending); // 降序
return 0;
}
- 异步处理:我不知道什么时候能算完
#include <thread>
#include <functional>
#include <iostream>
// 模拟异步任务
void asyncTask(std::function<void(int)> callback) {
std::thread([callback]() {
std::this_thread::sleep_for(std::chrono::seconds(2));
int result = 42; // 模拟计算结果
callback(result); // 完成后通过回调通知
}).detach();
}
// 回调处理结果
void handleResult(int result) {
std::cout << "异步任务完成,结果: " << result << std::endl;
}
int main() {
std::cout << "开始异步任务..." << std::endl;
asyncTask(handleResult); // 非阻塞调用
// 主线程可以继续做其他事情
for (int i = 0; i < 5; i++) {
std::cout << "主线程工作..." << i << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(500));
}
return 0;
}
实现
函数指针实现
普通函数调用
#include <iostream>
//回调函数 无参
void callBack(){
std::cout<<"无参回调函数"<<std::endl;
}
//回调函数 带参数
void callback_ii(int a,int b){
std::cout<<a+b<<std::endl;
}
//回调函数带返回值
int callback_return_i(){
int a = 10;
return a;
}
/*
定义函数指针
*/
//无参 函数指针
typedef void(*CallbackPtr)();
// 它是"指向返回void,接受两个int参数的函数"的指针类型
typedef void (*CallbackPtr_ii)(int, int);
// using CallbackPtr_using = void(*)(int, int);
//带返回值 函数指针
typedef int(*CallbackPtr_return_i)();
void performTask(CallbackPtr cb) {
cb(); // 执行回调
}
void performTask_ii(int a, int b, CallbackPtr_ii cb) {
// 业务逻辑...
cb(a, b); // 执行回调
}
void performTask_return_i(CallbackPtr_return_i cb) {
// 业务逻辑...
std::cout<< cb() <<std::endl;
}
int main(){
performTask(callBack);
performTask_ii(1,2,callback_ii);
performTask_return_i(callback_return_i);
return 0;
}
这里其实就是使用指针调用函数。
void (*p)(int ,int);
p = callback;
//p = &callback;
(*p)(0,1);
//p(0,1);
类成员函数和类静态函数调用
#include <iostream>
class MyClass {
public:
void Func(){
std::cout << "function" << std::endl;
}
static void staticFunc() {
std::cout << "Static function" << std::endl;
}
};
int main() {
void (*staticFuncPtr)() = &MyClass::staticFunc;
staticFuncPtr(); // 输出: Static function
/*
void (*funcPtr)() = &MyClass::Func;//error: cannot convert ‘void (MyClass::*)()’ to ‘void (*)()’ in initialization
funcPtr();
*/
// 指向普通成员函数 - 需要特殊的语法
MyClass MyObj;
void (MyClass::*FuncPtr)() = &MyClass::Func; // 声明成员函数指针
(MyObj.*FuncPtr)(); // 通过对象调用,输出: function
return 0;
}
Class A 调用 Class B
#include <iostream>
class ProgramA {
public:
void Func(void (*callback)()) {
std::cout << "A: callback" << std::endl;
callback();
}
};
class ProgramB {
public:
void Func() {
std::cout << "B: function" << std::endl;
}
static void staticFunc() {
std::cout << "B: Static function" << std::endl;
}
};
int main() {
ProgramA PA;
PA.Func(ProgramB::staticFunc);
return 0;
}
- 如何使用A调用B中的非静态方法?
这里只写两种方式。
方式一:使用function修改A的调用函数。
方式二:在A中修改参数
#include <iostream>
#include <functional>
class ProgramB;
class ProgramA {
public:
//方式一
void Func(std::function<void()> callback) {
std::cout << "A std::function<void(): callback" << std::endl;
callback();
}
//方式二
void Func(void(ProgramB::*callback)(),void *PBPtr){
std::cout << "A void(ProgramB::*callback)(): callback" << std::endl;
((ProgramB*)PBPtr->*callback)();//*不是解引用,而是指针到成员运算符 ->* 的一部分
}
};
class ProgramB {
public:
void Func() {
std::cout << "B: function" << std::endl;
}
static void staticFunc() {
std::cout << "B: Static function" << std::endl;
}
};
int main() {
ProgramA PA;
ProgramB PB;
PA.Func(ProgramB::staticFunc);
PA.Func([&PB](){
PB.Func();
});
PA.Func(&ProgramB::Func,&PB);
return 0;
}
Lambda表达式实现
- Lambda表达式语法
[捕获列表](参数列表) mutable exception -> 返回类型 { 函数体 }
void run(std::function<void()> cb) { cb(); }
int main() {
int secret = 42;
// 使用 Lambda 作为回调,并捕获局部变量 secret
run([secret]() {
std::cout << "数字是: " << secret << std::endl;
});
}
std::function 与 std::bind
C++11 引入的 std::function 是一个通用函数包装器。它可以存储、复制和调用任何“可调用对象”(函数指针、仿函数、Lambda、类成员函数
上面已经有关于function的内容,这里总结一下,
#include <iostream>
#include <functional>
class Program {
public:
void func(int status) {
std::cout << "func: " << status << std::endl;
}
static void staticFunc(){
std::cout << "staticFunc" << std::endl;
}
};
void gfunc(){
std::cout << "gfunc" << std::endl;
}
int main() {
//1, 类非静态函数
Program d;
// 绑定对象 d 到成员函数 onFinished
std::function<void(int)> cb_1 = std::bind(&Program::func, &d, std::placeholders::_1);
//std::placeholders::_1 这是一个占位符。
//由于 func(int status) 需要一个整数参数,但我们在绑定时还不知道这个参数的具体值(它要在未来触发回调时才由调用者传入)。
//_1 表示:这个位置的参数,请在未来调用 cb(value) 时,把第一个参数填到这里。
cb_1(200);
//2.类静态函数
std::function<void()> cb_2 = Program::staticFunc;
cb_2();
//3 普通函数
std::function<void()> cb_3 = gfunc;
cb_3();
//
std::function<void()> cb_4 = &gfunc;
cb_4();
}

浙公网安备 33010602011771号