C++ 回调函数

回调函数(Callback Function)是编程中常用的设计模式之一,通常用于异步任务的场景。回调函数的主要作用是在特定事件(例如消息到达、网络响应等)发生时自动执行用户定义的处理逻辑。常见的应用场景包括消息队列、网络通信、定时任务等。回调函数的优点在于它允许灵活的事件处理,让开发者定义在某些事件发生时执行的特定代码。

以下内容将介绍回调函数的基础知识、应用场景,并提供详细的注释和示例代码。

回调函数的基础知识

回调函数是一种函数指针(或函数对象),在特定条件下被调用。在 C++ 中,回调函数可以是普通函数、Lambda 表达式、类的成员函数等。通常的使用步骤如下:

  1. 定义一个回调函数(或传入函数对象)。
  2. 在事件发生时(如接收到消息或完成网络请求时),调用该回调函数并传递所需参数。
  3. 回调函数根据接收到的参数执行特定的操作。

应用场景

  • 消息队列:在消息队列中,消费者接收消息时可以使用回调函数处理消息。
  • 网络库:在网络通信中,客户端接收到服务器响应时可以使用回调函数处理报文。
  • 异步任务:例如文件读取、定时器任务,任务完成后使用回调函数通知调用方。

注意事项

  • 线程安全:如果回调函数涉及多线程操作,确保函数本身是线程安全的,避免竞态条件(Race Condition)。
  • 生命周期管理:确保回调函数对象的生命周期至少比事件源的长,避免回调函数在事件发生时对象已经被销毁。
  • 错误处理:在回调函数中尽量处理异常,避免异常未经处理导致程序崩溃。

超简单的回调函数示例

#include <iostream>

// 定义一个函数指针类型,用于回调
typedef void (*Callback)(int);

// 简单的数字处理函数
void process(int number, Callback callback) {
    std::cout << "处理数字: " << number << std::endl;
    // 调用回调函数
    callback(number);
}

// 用户定义的回调函数
void printSquare(int number) {
    std::cout << "平方结果: " << number * number << std::endl;
}

int main() {
    // 调用处理函数,并传入数字和回调函数
    process(5, printSquare);  // 输出: 处理数字: 5
    // 输出: 平方结果: 25

    return 0;
}

代码讲解

  1. 定义函数指针类型

    • 使用 typedef 定义一个函数指针类型 Callback,该指针指向返回类型为 void 且接受一个 int 参数的函数。
  2. process 函数

    • 接受一个整数 number 和一个回调函数 callback。它会打印出处理的数字,并调用传入的回调函数。
  3. printSquare 函数

    • 这是用户定义的回调函数,接受一个整数并打印它的平方。
  4. main 函数

    • 在主函数中,调用 process 函数,并传入数字 5 和回调函数 printSquare

运行结果

处理数字: 5
平方结果: 25

可以定义一个回调函数,它接受一个布尔值表示操作是否成功,以及一个数据参数。下面是一个简单的示例,演示如何实现这种模式。

#include <iostream>

// 定义回调函数类型
typedef void (*Callback)(bool success, int data);

// 简单的数字处理函数
void process(int number, Callback callback) {
    std::cout << "处理数字: " << number << std::endl;
    
    // 假设处理成功,并生成数据
    int resultData = number * number; // 计算平方

    // 调用回调函数,传递成功标志和数据
    callback(true, resultData);
}

// 用户定义的回调函数
void mresp(bool success, int data) {
    if (success) {
        std::cout << "操作成功,结果数据: " << data << std::endl;
    } else {
        std::cout << "操作失败" << std::endl;
    }
}

int main() {
    // 调用处理函数,并传入数字和回调函数
    process(5, mresp);  // 输出: 处理数字: 5
                         // 输出: 操作成功,结果数据: 25

    return 0;
}
 

代码讲解

  1. 定义回调函数类型

    • 使用 typedef 定义一个回调函数类型 Callback,它接受一个布尔值和一个整数作为参数。
  2. process 函数

    • 接受一个整数 number 和一个回调函数 callback。它会打印出处理的数字,假设处理成功并计算平方,然后调用回调函数。
  3. 用户定义的回调函数 mresp

    • 该函数接受一个布尔值 success 和一个整数 data。根据 success 的值,它将输出操作成功与否的消息,并打印相关的数据。
  4. main 函数

    • 在主函数中,调用 process 函数,并传入数字 5 和回调函数 mresp

运行结果

运行该程序会输出:

处理数字: 5
操作成功,结果数据: 25

回调函数实现:消息队列与网络库示例

以下是一个示例,演示如何在消息队列和网络库中使用回调函数。

示例一:消息队列中的回调函数

#include <iostream>
#include <functional>
#include <queue>
#include <thread>
#include <mutex>
#include <condition_variable>

// 模拟消息结构
struct Message {
    int id;
    std::string content;
};

// 消息队列类
class MessageQueue {
public:
    using Callback = std::function<void(const Message &)>;

    // 注册回调函数
    void registerCallback(Callback callback) {
        this->callback = callback;
    }

    // 生产消息
    void produceMessage(int id, const std::string &content) {
        std::lock_guard<std::mutex> lock(queueMutex);
        messages.push({ id, content });
        cv.notify_one();  // 通知消费者有新消息
    }

    // 消费消息(启动消息处理线程)
    void startProcessing() {
        std::thread([this]() {
            while (true) {
                Message msg;
                {
                    std::unique_lock<std::mutex> lock(queueMutex);
                    cv.wait(lock, [this]() { return !messages.empty(); });
                    msg = messages.front();
                    messages.pop();
                }
                // 回调用户自定义的处理函数
                if (callback) {
                    callback(msg);
                }
            }
                    }).detach();
    }

private:
    std::queue<Message> messages;
    std::mutex queueMutex;
    std::condition_variable cv;
    Callback callback;  // 用户定义的回调函数
};

// 消息处理函数
void handleMessage(const Message &msg) {
    std::cout << "处理消息: ID = " << msg.id << ", 内容 = " << msg.content << std::endl;
}

// 主函数
int main() {
    MessageQueue queue;

    // 注册回调函数
    queue.registerCallback(handleMessage);

    // 启动消息处理线程
    queue.startProcessing();

    // 模拟生产消息
    queue.produceMessage(1, "Hello, World!");
    queue.produceMessage(2, "回调函数示例");

    std::this_thread::sleep_for(std::chrono::seconds(2));
    return 0;
}

注释:

  1. MessageQueue 是消息队列类,它包含一个消息队列(std::queue<Message>)和回调函数 Callback
  2. registerCallback 用于注册用户自定义的回调函数。startProcessing 启动一个消费者线程,在有新消息时调用用户的回调函数。
  3. handleMessage 是自定义的回调函数,当消息到达时自动调用并处理消息。
  4. produceMessage 用于生产新消息并通知消费者处理。
示例二:网络库中的回调函数

#include <iostream>
#include <functional>
#include <thread>
#include <chrono>

// 模拟网络响应
struct NetworkResponse {
    int statusCode;
    std::string body;
};

// 网络类
class NetworkClient {
public:
    using Callback = std::function<void(const NetworkResponse &)>;

    // 注册回调函数
    void registerCallback(Callback callback) {
        this->callback = callback;
    }

    // 模拟发送请求并处理响应
    void sendRequest(const std::string &url) {
        std::thread([this, url]() {
            std::this_thread::sleep_for(std::chrono::seconds(1));  // 模拟网络延迟
            NetworkResponse response = { 200, "Response from " + url };
            // 回调用户自定义的函数对象处理响应
            if (callback) {
                callback(response);
            }
                    }).detach();
    }

private:
    Callback callback;  // 用户定义的回调函数
};

// 处理网络响应的函数
void handleResponse(const NetworkResponse &response) {
    std::cout << "处理网络响应: 状态码 = " << response.statusCode
        << ", 响应体 = " << response.body << std::endl;
}

// 主函数
int main() {
    NetworkClient client;

    // 注册回调函数
    client.registerCallback(handleResponse);

    // 发送网络请求
    client.sendRequest("http://baidu.com");

    std::this_thread::sleep_for(std::chrono::seconds(2));  // 等待响应处理完成
    return 0;
}

注释:

  1. NetworkClient 模拟了一个简单的网络客户端,用户可以通过 registerCallback 注册处理网络响应的回调函数。
  2. sendRequest 模拟了一个异步请求,网络响应通过回调函数 Callback 处理。
  3. handleResponse 是处理网络响应的回调函数,打印了响应的状态码和内容。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值