【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();
}
posted @ 2026-01-07 01:14  hjk-airl  阅读(33)  评论(0)    收藏  举报