一文搞懂回调函数

先解释名字:

你调库就是调用,库调你就是回调;

工作中常见的应用是什么呢?

比如甲,乙合作完成一个功能,甲的functionA里面会调用乙的functionB,那么乙就会将functionB作为回调函数传给甲,乙这个行为就是注册回调函数,甲就可以合适的时间调用functionB

为什么甲不直接调用乙的functionB?

1.甲和乙可以独立地进行开发和维护,比如functionB还没写,怎么调用呢

2.丙,丁同样可以通过注册回调的方式让甲调用

(比如客户端开发时,A点击鼠标触发A响应,B点击鼠标触发B响应,那么组件库会提供一个接口给A,B注册回调,总不能组件库会挨个调用A,B的响应函数吧)

#include <functional>

class Component_A {
public:
    using Callback = std::function<void()>;

    void registerCallback(Callback callback) {
        callback_ = std::move(callback);
    }

    void unregisterCallback() {
        callback_ = nullptr;
    }

    void functionA() {
        std::cout << "Component A is doing something..." << std::endl;
        if (callback_) {
            callback_();
        }
    }

private:
    Callback callback_;
};

class Component_B {
public:
    void functionB() {
        std::cout << "Component B is doing its thing." << std::endl;
    }
};

int main() {
    Component_A componentA;
    Component_B componentB;

    // 乙将自己的 functionB 作为回调函数,注册给甲
    componentA.registerCallback(std::bind(&Component_B::functionB, &componentB));

    // 甲会在适当的时候调用乙注册的回调函数
    std::cout << "Calling Component A's functionA..." << std::endl;
    componentA.functionA();

    // 取消注册回调函数
    componentA.unregisterCallback();

    return 0;
}

贴一个基本的异步和回调的组合应用

使用 std::thread 和回调函数来实现异步读取文件

#include <iostream>
#include <thread>
#include <functional>
#include <fstream>
#include <string>

// 回调函数类型
using FileReadCallback = std::function<void(const std::string&)>;

// 异步读取文件的函数
void readFileAsync(const std::string& filename, FileReadCallback callback) {
    std::ifstream file(filename);
    if (file.is_open()) {
        std::string content((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
        std::cout << "Start" << std::endl;
        std::this_thread::sleep_for(std::chrono::seconds(10));
        callback(content);
    } else {
        callback(""); // 传递空字符串表示读取失败
    }
}

int main(int argc, char* argv[]) {
    std::thread fileReadThread([](const std::string& filename, FileReadCallback callback) {
        readFileAsync(filename, callback);
    }, "D:\\TEST\\example.txt", [](const std::string& content) {
        std::cout << "File content: " << content << std::endl;
    });
    fileReadThread.detach();

    std::cout << "still" << std::endl;

    // 继续执行其他任务
    // ...

    return 0;
}

接下来,我们使用 std::async 替换掉std::thread和回调来启动异步任务。

std::async 的第一个参数 std::launch::async 表示创建一个新线程来执行任务,而不是在当前线程中执行。第二个参数是要执行的函数,第三个及后续参数是函数的参数。

 std::async 会自动创建和管理线程,不需要我们手动控制线程的生命周期。并且std::async 返回一个 std::future 对象,可以很方便地获取异步任务的返回值。

#include <iostream>
#include <future>
#include <functional>
#include <fstream>
#include <string>

// 异步读取文件的函数
std::string readFileAsync(const std::string& filename) {
    std::ifstream file(filename);
    if (file.is_open()) {
        std::string content((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
        std::cout << "Start" << std::endl;
        std::this_thread::sleep_for(std::chrono::seconds(10));
        return content;
    } else {
        return ""; // 返回空字符串表示读取失败
    }
}

int main(int argc, char* argv[]) {
    // 启动异步任务读取文件内容
    std::future<std::string> fileContentFuture = std::async(std::launch::async, readFileAsync, "D:\\TEST\\example.txt");

    std::cout << "still" << std::endl;

    // 等待异步任务完成并获取结果
    std::string fileContent = fileContentFuture.get();
    std::cout << "File content: " << fileContent << std::endl;

    return 0;
}

  • 7
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值