回调函数CallBack的一些用法总结

回调函数callback

回调函数(Callback Function)是一种 通过函数指针或函数对象传递,并在特定事件发生时调用的函数。它用于 解耦逻辑,尤其适用于 事件驱动编程、异步操作、信号处理、线程池、多线程编程 等场景。

1. C语言方式

1.1 函数指针方式

在 C 语言中,回调函数通常是 通过函数指针传递,然后在需要的时候调用。

#include <stdio.h>

// 定义回调函数类型
typedef void (*CallBack_name)(int, const char *str);

// 回调函数的实现
void myCallbackFunc(int value, const char *info) {
    printf("回调函数被调用,值: %d, info: %s\n", value, info);
}

// 一个接受回调函数的函数
void processData(int data, CallBack_name callback) {
    printf("处理数据: %d\n", data);
    callback(data, "process done!"); // 触发回调
}

int main() {
    processData(42, myCallbackFunc); // 传入回调函数
    return 0;
}

这里解释一下typedef void (*CallBack_name)(int);的用法:

typedef void (*CallBack_name)(int, const char *str);

//是 C 语言 和 C++ 中 定义函数指针类型 的一种方式。它的作用是 定义一个新的类型 CallBack_name,该类型表示指向一个接受 int 参数并返回 void 的函数的指针。
// 1. void 表示函数的返回类型;
// 2. (*CallBack_name) 表示函数指针(CallBack_name 表示为函数指针的名称);
// 3. (int, const char *str) 表示函数的参数列表;
// 4. typedef 表示为这个复杂的类型起一个别名;相当于为函数指针: void (*CallBack_func)(int, const char *str); 起了一个别名CallBack_name,后续可以直接使用CallBack_name,就像使用普通类型那样。

// 若不使用typedef,则前面的代码与下面的代码等价:
#include <stdio.h>
void myCallbackFunc(int value, const char *info) {
    printf("回调函数被调用,值: %d, info: %s\n", value, info);
}
void processData(int data, void (*func)(int value, const char *info)) {
    printf("处理数据: %d\n", data);
    func(data, "process done!");
}
int main() {
    processData(42, myCallbackFunc);
    return 0;
}
// 这样写可读性比较差,所以 typedef 可以 简化 代码,使代码更清晰易读。
// 代码更清晰,减少了冗长的函数指针写法。
// 可以像使用普通类型一样使用函数指针。
// 在 struct 或 class 里更方便使用。

更丰富一些的用法:

#include <stdio.h>

typedef int (*setInfoCB_t)(int, const char *);

int setInfoCbFunc(int age, const char *name) {
    printf("callback: age: %d, name: %s\n", age, name);
    return 10;
}

void processInfo(int age, setInfoCB_t callback) {
    printf("get info: %d\n", age);
    printf("callback ret = %d \n", callback(age * 2, "Rekko"));
}

int main() {
    setInfoCB_t mInfoCb = NULL;
    mInfoCb = setInfoCbFunc;

    processInfo(12, mInfoCb); 
    return 0;
}

2. C++方式

2.1 函数指针方式

C++11 及以上版本,可以用 using 替代 typedef来声明函数指针,写法更加直观:

如:using setInfoCB_t = int (*)(int, const char *);

#include <stdio.h>

using setInfoCB_t = int (*)(int, const char *);

int setInfoCbFunc(int age, const char *name) {
    printf("callback: age: %d, name: %s\n", age, name);
    return 10;
}

void processInfo(int age, setInfoCB_t callback) {
    printf("get info: %d\n", age);
    printf("callback ret = %d \n", callback(age * 2, "Rekko"));
}

int main() {
    setInfoCB_t mInfoCb = nullptr;
    mInfoCb = setInfoCbFunc;

    processInfo(12, mInfoCb); 
    return 0;
}

2.2 std::function 方式

在 C++ 中,我们可以使用 std::function 作为回调函数的类型,它比传统的函数指针更灵活,可以接收 普通函数、Lambda 表达式、成员函数、仿函数等

如:using setInfoCB_t = std::function<int(int, const char *)>;

#include <iostream>
#include <functional>   // 引入std::function

using setInfoCB_t = std::function<int(int, const char *)>;

int setInfoCbFunc(int age, const char *name) {
    std::cout << "callback: age: " << age << ", name: " << name << std::endl;
    return 10;
}

void processInfo(int age, setInfoCB_t callback) {
    std::cout << "get info: " << age << std::endl;
    int ret = callback(age * 2, "Rekko");
    std::cout << "callback ret = " << ret << std::endl;
}

#if 0   // 普通函数
int main() {
    setInfoCB_t mInfoCb = nullptr;
    mInfoCb = setInfoCbFunc;

    processInfo(12, mInfoCb); 
    return 0;
}
#endif

#if 1   // Lambda表达式
int main() {
    processInfo(12, [](int age, const char *name) {
        std::cout << "Lambda callback: age: " << age << ", name: " << name << std::endl;
        return 1;
    }); 
    return 0;
}
// or 
//int main() {
//    setInfoCB_t mInfoCb = nullptr;
//    mInfoCb = [](int age, const char *name) {
//        std::cout << "Lambda callback: age: " << age << ", name: " << name << std::endl;
//        return 1;
//    };
//
//    processInfo(12, mInfoCb); 
//    return 0;
//}
#endif

2.3 C++成员函数作为回调

C++ 成员函数不能直接作为普通回调函数传递,因为它们有一个 隐式的 this 指针,需要使用 std::bind 或 Lambda 转换。

示例:使用 std::bind 传递成员函数
#include <iostream>
#include <functional>

class Processor {
public:
    void memberCallback(int value) {
        std::cout << "成员函数回调被调用,值: " << value << std::endl;
    }

    void run() {
        // 绑定成员函数作为回调
        processData(77, std::bind(&Processor::memberCallback, this, std::placeholders::_1));
    }

private:
    using Callback = std::function<void(int)>;

    void processData(int data, Callback callback) {
        std::cout << "处理数据: " << data << std::endl;
        callback(data); // 调用回调
    }
};

int main() {
    Processor p;
    p.run();
    return 0;
}

2.4 C++仿函数(函数对象)作为回调

仿函数(Functors)是 重载 operator() 的类对象,可以像函数一样调用,并可以存储状态。

#include <iostream>
#include <functional>

// 定义仿函数
class FunctorCallback {
public:
    void operator()(int value) const {
        std::cout << "仿函数回调被调用,值: " << value << std::endl;
    }
};

// 处理数据并调用回调
void processData(int data, std::function<void(int)> callback) {
    std::cout << "处理数据: " << data << std::endl;
    callback(data);
}

int main() {
    FunctorCallback functor;
    processData(55, functor); // 传递仿函数作为回调
    return 0;
}

总结

方式适用场景特点
C 函数指针纯 C 代码、简单回调轻量级,但不支持成员函数
std::functionC++ 回调函数更灵活,支持 Lambda、成员函数、仿函数
成员函数回调面向对象编程需要 std::bind 或 Lambda 适配
仿函数需要状态的回调可存储状态,复用性强
Lambda一次性回调,简洁适用于小型回调函数

回调函数是一种强大的编程技巧,在异步编程、事件驱动、网络编程、GUI 交互等场景中广泛应用。C++11 及更高版本中,std::functionstd::bind 让回调更加灵活。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值