【C++】传递‘类非静态成员函数’用作回调函数

在C语言中,传递函数指针是非常常见的操作。

在C++语言中,使用C语言一致的方法传递全局函数指针,或者传递静态函数指针也很常见。

不过如果遇到想传递非静态成员函数时,可以参考以下示例代码。

cpp 复制代码
#ifndef _WORKER_HPP_
#define _WORKER_HPP_

#include <iostream>
#include <unistd.h>
#include <functional>
#include <chrono>
#include <iomanip>
#include <sstream>


class Worker {
public:
    // 设置回调函数
    void registerCallback(std::function<void(int, std::string, long)> cb) {
        this->mCallback = cb;
    }

    void startWork() {
        using namespace std::literals;

        const std::chrono::time_point<std::chrono::system_clock> now = std::chrono::system_clock::now();
        const std::time_t t_c = std::chrono::system_clock::to_time_t(now);

        int i = 1008;
        std::stringstream ss;
        ss << std::put_time(std::localtime(&t_c), "%F %T");
        std::string s = ss.str();
        long l = __cplusplus;

        mCallback(i, s, l);
    }

private:
    std::function<void(int, std::string, long)> mCallback;

};

#endif

参考Manager内的work函数,列出了几种写法。

cpp 复制代码
#ifndef _MANAGER_HPP_
#define _MANAGER_HPP_

#include <functional>
#include <string>
#include <iostream>

#include "worker.hpp"

class Manager {
public:

    Manager(): mI(-1), mS("coco"), mL(-1L) {
        
    }

    virtual ~Manager() = default;

public:
    void work() {
        using namespace std::placeholders;
        // 设置回调函数, 使用lambda
        worker.registerCallback([this](int&& i, std::string&& s, long&& l) -> void {
            this->onMsgCallback(i, s, l);
        });

        // 设置回调函数,使用bind,搭配mem_fn
        auto ptr = std::mem_fn(&Manager::onMsgCallback);
        worker.registerCallback(std::bind(ptr, this, _1, _2, _3));

        // 不搭配mem_fn
        worker.registerCallback(std::bind(&Manager::onMsgCallback, this, _1, _2, _3));

        worker.startWork();
    }

    void print() {
        std::cout << __FUNCTION__ << " mI is " << mI << ", mS is " << mS << ", mL is " << mL << std::endl;
    }

private:
    void onMsgCallback(int i, std::string s, long l) {
        std::cout << __FUNCTION__ << " i is " << i << ", s is " << s << ", l is " << l << std::endl;
        this->mI = i;
        this->mS = s;
        this->mL = l;
    }

private:
    int mI;

    std::string mS;

    long mL;

    Worker worker;
};

#endif

main示例:

cpp 复制代码
int main()
{
    // 演示将非静态成员函数设置为回调函数
    {
        Manager manager;
        manager.print();
        manager.work();
        manager.print();
    }
    return 0;
}

输出参考:

print mI is -1, mS is coco, mL is -1

onMsgCallback i is 1009, s is 2023-11-18 20:22:34, l is 201402

print mI is 1009, mS is 2023-11-18 20:22:34, mL is 201402

相关推荐
坚果派·白晓明27 分钟前
【鸿蒙PC三方库移植适配框架解读系列】第八篇:扩展lycium框架使其满足rust三方库适配
c语言·开发语言·华为·rust·harmonyos·鸿蒙
花间相见33 分钟前
【PaddleOCR教程01】PP-OCRv5 全面指南:从模型架构到实战部署
开发语言·r语言
小短腿的代码世界1 小时前
Qt 股票订单撮合引擎:高频交易系统的核心心脏
开发语言·数据库·qt·系统架构·交互
REDcker1 小时前
C++变量存储与ELF段布局详解 从const全局到rodata与nm_readelf验证实践
java·c++·面试
谙弆悕博士3 小时前
快速学C语言——第16章:预处理
c语言·开发语言·chrome·笔记·创业创新·预处理·业界资讯
yuan199973 小时前
基于 C# 实现的 Omron HostLink (FINS) 协议 PLC 通讯
开发语言·c#
王老师青少年编程3 小时前
csp信奥赛C++高频考点专项训练之字符串 --【字符串排序】:合并序列
c++·字符串·csp·高频考点·信奥赛·字符串排序·合并序列
qq_422828624 小时前
android图形学之SurfaceControl和Surface的关系 五
android·开发语言·python
handler014 小时前
UDP协议与网络通信知识点
c语言·网络·c++·笔记·网络协议·udp
如竟没有火炬4 小时前
用队列实现栈
开发语言·数据结构·python·算法·leetcode·深度优先