C++实现回调(一)

2023-12-26 19:09:25

通过函数指针在其他地方调用函数的过程称为回调,被调用的函数称为回调函数,函数指针通过传参方式传递。在C++的实际应用中,有很多实现回调函数的方式,不一定要传递函数指针才能实现回调,只要实现了回调的功能,都叫回调函数。
需要注意:回调函数是和调用者在同一线程,使用中要注意线程安全。

一、虚函数实现回调

这是最具C++特征的回调函数,基类定义纯虚函数,派生类实现虚函数,基类指针可以指向派生类,使用基类指针就可以调用派生类的虚函数,从而实现回调。
不足:利用虚函数特性实现回调函数的方式需要定义基类,通常是子类对父类的回调,当子类层级太多时需要逐级回调,实现起来比较繁琐。

二、结构体指针实现回调函数

把全局回调函数的指针、回调对象的指针封装在一个结构体里,把这个结构体指针传递给子类,子类的子类等等,可以在程序的任何地方实现回调。

可以把结构体理解为一个触发器,统一管理回调函数以及回调对象(经理类),然后在系统内部进行调用(职员),这也以为着职员是想对底层的存在,实际执行者。

managercon.h

#ifndef MANAGERCON_H
#define MANAGERCON_H

#include <string>
//回调结构体
struct ChwContext {
    //data      回调数据指针
    //nb_data   回调数据长度
    //user_this 指向当前结构体的指针
    void (*receiveQt)(char *data, int nb_data,void* user_this);
    void *user_callback;//回调函数所在对象的指针
};
#define safe_delete(a) {if( (a)) {delete (a); (a) = NULL;}}
#define safe_deleteA(a) {if( (a)) {delete[] (a); (a) = NULL;}}
#define safe_free(a) {if( (a)) {free((a)); (a) = NULL;}}

class EmployeeCON//员工类
{
public:
    EmployeeCON(ChwContext *pcontext){
        pChwContext = pcontext;
    }
    ChwContext *pChwContext;//由父对象传递过来的回调结构体指针

    void dowork(int count){
        int sum = 0;
        for(int index=0;index<count;index++)
            sum += index*10;

        std::string tmpstr = "total:" + std::to_string(sum);
        pChwContext->receiveQt((char*)tmpstr.c_str(),tmpstr.size(),pChwContext);//执行回调
    }
};

class ManagerCON//经理类
{
public:
    ManagerCON();
    ~ManagerCON();

    void sendwork(int count);
    void callback_receive(std::string msg);//回调函数
private:
    ChwContext *p_ChwContext;//回调结构体,在回调函数所在对象声明和定义,可传递给子类,子类的子类等
    EmployeeCON *pEmployeeCON;
};

#endif // MANAGERCON_H

managercon.cpp

#include "managercon.h"
//全局回调函数
void g_callback_receive(char *data, int nb_data ,void *obj) {
    if (obj == nullptr)
        return;
    ChwContext  *contx = (ChwContext*) obj;
    ManagerCON *mc = (ManagerCON*) contx->user_callback;
    std::string tmpstr(data,nb_data);
    mc->callback_receive(tmpstr);
}

ManagerCON::ManagerCON()
{
    p_ChwContext = new ChwContext;
    p_ChwContext->receiveQt = g_callback_receive;
    p_ChwContext->user_callback = this;

    pEmployeeCON = new EmployeeCON(p_ChwContext);
}

ManagerCON::~ManagerCON()
{
    safe_delete(pEmployeeCON);
    safe_delete(p_ChwContext);
}

void ManagerCON::sendwork(int count)
{
    pEmployeeCON->dowork(count);
}

void ManagerCON::callback_receive(std::string msg)
{
    printf("msg=%s\n",msg.c_str());
}

运行

ManagerCON mManagerCON;
mManagerCON.sendwork(10);

?三、C++11新特性td::tr1::function和std::tr1::bind实现回调函数

与c#写法类型,定义回调函数入库,然后再定义回调方法与之绑定,实现回调函数调用收,执行回调方法。

managerbind.h

#ifndef MANAGERBIND_H
#define MANAGERBIND_H

#include <iostream>
#include <tr1/functional>
#include <string>
class employeeBind{//员工类
public:
    employeeBind(){
    }
    void dowork(int count){
        int sum = 0;
        for(int index=0;index<count;index++)
            sum += index*10;
        std::string msg = "total:" + std::to_string(sum);
        if(Callback)
            Callback(msg);//回调函数
    }
    std::tr1::function<void(std::string)> Callback;
};

class ManagerBind//经理类
{
public:
    ManagerBind();

    employeeBind memployeeBind;
    void sendwork(int num);
    void callbackBD(std::string msg);
};

#endif // MANAGERBIND_H

managercon.cpp

#include "managercon.h"
//全局回调函数
void g_callback_receive(char *data, int nb_data ,void *obj) {
    if (obj == nullptr)
        return;
    ChwContext  *contx = (ChwContext*) obj;
    ManagerCON *mc = (ManagerCON*) contx->user_callback;
    std::string tmpstr(data,nb_data);
    mc->callback_receive(tmpstr);
}

ManagerCON::ManagerCON()
{
    p_ChwContext = new ChwContext;
    p_ChwContext->receiveQt = g_callback_receive;
    p_ChwContext->user_callback = this;

    pEmployeeCON = new EmployeeCON(p_ChwContext);
}

ManagerCON::~ManagerCON()
{
    safe_delete(pEmployeeCON);
    safe_delete(p_ChwContext);
}

void ManagerCON::sendwork(int count)
{
    pEmployeeCON->dowork(count);
}

void ManagerCON::callback_receive(std::string msg)
{
    printf("msg=%s\n",msg.c_str());
}

参考资料

C++实现回调函数的几种方式_c++ 回调-CSDN博客

文章来源:https://blog.csdn.net/cangqiongxiaoye/article/details/135219282
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。