C++实现回调函数的几种方式

五种将c++类的成员函数用作回调函数的方法——史上最全、最简!!! 前言 在写ROS的cpp代码时发现回调函数十分的常用,然后初学的时候没有深入研究过,记录下几种用法,据说在写线程的时候也很常用。方法五应该是最简单实用的了… 方法一 先从最简单的入手,直接使用普通函数用作回调函数。 #include "pch.h" #include <iostream> using namespace std; class TestCallback { public:... 阅读详情

目录
C++虚函数特性实现回调函数
C++结构体指针实现回调函数
C++11新特性td::tr1::function和std::tr1::bind实现回调函数
C++联合体union实现回调函数

通常认为通过函数指针在其他地方调用函数的过程称为回调,被调用的函数称为回调函数,函数指针通过传参方式传递。
在C++的实际应用中,有很多实现回调函数的方式,不一定要传递函数指针才能实现回调,只要实现了回调的功能,都叫回调函数。
回调函数是和调用者在同一线程,使用中要注意线程安全。
本章通过几个例子介绍C++实现回调函数的几种方式。
C++虚函数特性实现回调函数
这是最具C++特征的回调函数,基类定义纯虚函数,派生类实现虚函数,基类指针可以指向派生类,使用基类指针就可以调用派生类的虚函数,从而实现回调。
不足:利用虚函数特性实现回调函数的方式需要定义基类,通常是子类对父类的回调,当子类层级太多时需要逐级回调,实现起来比较繁琐。
代码实现:

#ifndef MANAGERINH_H
#define MANAGERINH_H

#include<string>
using namespace std;
class messageBase {//消息回调基类
public:
    messageBase() {};
    virtual ~messageBase() {};
    virtual void msgCallback(std::string msg)=0;
};

class employeeINH{//员工类
public:
    employeeINH(messageBase *msgBase){
        m_messageBase = msgBase;
    }
    void dowork(int count) {
        int sum = 0;
        for(int index=0;index<count;index++)
            sum += index*10;
        std::string msg = "total:" + to_string(sum);
        if(m_messageBase)
            m_messageBase->msgCallback(msg);//回调函数
    }
private:
    messageBase *m_messageBase;//消息回调基类对象指针,可以指向它的派生类,也就是 ManagerINH
};

class ManagerINH : public messageBase{//经理类,继承于消息回调基类
public:
    ManagerINH(){
        //创建子对象时,把父对象的指针传递过去
        pemployeeINH = new employeeINH(this);
    }

    virtual void msgCallback(std::string msg){//实现虚函数
        printf("result=%s\n",msg.c_str());
    }

    void sendwork(int num){
        pemployeeINH->dowork(num);
    }
private:
    employeeINH *pemployeeINH;
};
#endif // MANAGERINH_H

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
调用测试

ManagerINH mManagerINH;
mManagerINH.sendwork(10);
1
2
打印

result=total:450
1
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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
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());
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
调用测试

ManagerCON mManagerCON;
mManagerCON.sendwork(10);
1
2
打印

msg=total:450
1
C++11新特性td::tr1::function和std::tr1::bind实现回调函数
关于新特性参考:C++ std::tr1::function和std::tr1::bind模板类介绍,qt测试,这里不多说,直接上代码。
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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
managerbind.cpp

#include "managerbind.h"

ManagerBind::ManagerBind()
{
    memployeeBind.Callback = std::tr1::bind(&ManagerBind::callbackBD,this, std::tr1::placeholders::_1);
}

void ManagerBind::sendwork(int num){
    memployeeBind.dowork(num);
}

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
调用测试

ManagerBind mManagerBind;
mManagerBind.sendwork(10);
1
2
打印

msg=total:450
1
C++联合体union实现回调函数
union也叫联合体,在一个“联合体”内可以定义多种不同数据类型的变量,这些变量共享同一段内存,存储在内存中的起始地址相同,使用了覆盖计数,以达到节省空间的目的。union变量所占用的内存长度等于最长的成员变量的内存长度。
union的其中一个作用是实现简洁的线程回调函数。
managerunion.h

#ifndef MANAGERUNION_H
#define MANAGERUNION_H
#include <pthread.h>
#include <iostream>
#include <string>

class ManagerUnion;
//定义函数指针数据类型
typedef void* (ManagerUnion::*ThreadMeth)(void *);
typedef void* (*pThreadMethod)(void *);
class ManagerUnion
{
public:
    ManagerUnion();
    void startThread();
    void callbackUM(void *);
    int count;
    pthread_t m_threadID;
};
#endif // MANAGERUNION_H

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
managerunion.cpp

#include "managerunion.h"
ManagerUnion::ManagerUnion()
{
    count = 502;
    printf("ManagerUnion::ManagerUnion tid = %lu\n", pthread_self());
}

void ManagerUnion::startThread()
{
    union{//两个函数指针共享同一段内存
        pThreadMethod pFunc;
        void* (ManagerUnion::*ThreadMeth)(void *);
    }obj;

    obj.ThreadMeth = (ThreadMeth)&ManagerUnion::callbackUM;
    pthread_create(&m_threadID,0,obj.pFunc,this);//创建线程
}

//回调函数,也是线程处理函数,在子线程运行,调用的还是主类的函数
void ManagerUnion::callbackUM(void *)
{
    printf("ManagerUnion::callbackUM tid = %lu\n", pthread_self());

    printf("count=%d\n",count);
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
调用测试

ManagerUnion mManagerUnion;
mManagerUnion.startThread();
1
2
打印

ManagerUnion::ManagerUnion tid = 139898503038848
ManagerUnion::callbackUM tid = 139898191017728
count=502
————————————————
版权声明:本文为优快云博主「夏天匆匆2过」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.youkuaiyun.com/weixin_40355471/article/details/128658573

【c++】回调函数(callback function) 之前没有用过回调函数,这次突然用上,搜了一下其他大佬写的文章,看完之后还是云里雾里,所以决定自己从最简单的入手重新梳理一遍。 1.回调函数的概念 所谓回调函数,就是把其他函数作为自己的参数。 这里涉及到取地址的概念,为了思路不那么乱我们重新梳理一遍: 对于一个参数A,&A是取A的地址; 对于一个地址address,*address是取该地址下的值。 (int* b = &a; 对于... 阅读详情

相关推荐

Objective C++实现回调函数

下面为大家介绍一下在Objective C++中怎么样去实现回调,大家都知道Object C 与 C++ 混编的时候,是不能用Cocoa 自带的委托机制来实现回调的。比如在做一些多平台的项目时,由于接口是c++编写的,这个时候你要怎么样去将接口函数里的数据传递到你Object C编写的对象中去呢。最简单的方法就是使用ios消息机制-Notification,来传递从接口中收到的数据。但如果这个时候

IOS开发 4678

【C++】C++回调函数基本用法(详细讲解)

回调函数可以被简单地理解为:A函数作为参数传递给B函数,然后B函数在执行的某一时刻调用A函数。这里的A函数就是回调函数。

测试开发自动化 1万+

【RK3588 NPU性能调优实战】多线程异步推理YOLOv5,榨干6TOPS算力

本文详细解析了如何在RK3588 NPU上通过多线程异步推理优化YOLOv5目标检测性能,实现6TOPS算力的最大化利用。通过线程池设计、流水线化帧处理及避开内存带宽瓶颈等技巧,将NPU利用率从30%提升至82%,帧率显著提高至61.2FPS。文章还提供了环境配置、代码实现及性能对比数据,助力开发者高效部署AI模型。

weixin_29034963的博客 340

c++回调函数详解及实现(lambda)

回调函数就是一个被作为参数传递的函数。在C语言中,回调函数只能使用函数指针实现,在C++语言中还可以使用仿函数或匿名函数。回调函数的使用可以大大提升编程的效率,这使得它在现代编程中被非常多地使用。

猫哥 的沉淀、积累、总结。天天学习,好好向上...c/c++,嵌入式 linux,Android,HarmonyOS,AIOT) 8561

【Azure 架构师学习笔记】- Azure Private Endpoint

公有云的其中一个特点是默认允许公网访问, 这就对企业环境带来风险,也是很多年前企业对公有云抵触的其中一个原因,现在这类问题已经很少,因为有了很多技术来确保云上的资源被安全地访问。其中Private endpoint(PE)就起到了很重要的作用。云上的某个资源如VM会创建在特定的网络(VNet/Subnet)上, 而其他如Storage Account , Azure SQL等PaaS服务则没有。如果你需要用VM 来访问这些PaaS资源,VM 就会通过资源的公网IP 来访问。

MVP黄钊吉(發糞塗牆) 1786

手把手教你搞定国民技术N32G031的Keil开发环境(附Pack包和JLink配置)

本文详细指导如何搭建国民技术N32G031的Keil开发环境,包括Keil MDK安装与激活、Pack包导入、JLink调试器配置等关键步骤。特别针对新手常见问题提供解决方案,帮助开发者快速上手N32G031系列MCU的开发工作。

cuangu9341的博客 419

C++中实现回调的几种方式

考虑两个类之间的异步场景:客户端调用类A处理某个任务,A需要委托B进行一些处理并返回结果;并且都是异步进行,即函数迅速返回之后在后台进行计算,完毕后通知调用者。 一、使用函数指针 类B需要有SetCallBack接口来接收函数指针,此处我们用std::function来实现。 B在进行ProcessAsync任务时另起一个线程并detach掉去进行较长时间的后台计算(此处用std::this_thread::sleep_for来模拟长时间计算),计算完成后通过刚才设置进来的函数指针来通知调用者。 #

茶佬牛逼 1万+

MacBook Pro 合盖省电终极配置:pmset 5条命令实现一夜掉电<1%

本文详细介绍了如何通过5条pmset终端命令优化MacBook Pro的合盖休眠设置,实现一夜掉电<1%的极致省电效果。针对M系列芯片的特性,文章解析了MacOS的休眠机制,并提供电池模式与电源模式的差异化配置方案,帮助用户显著提升续航表现。

weixin_33824385的博客 476

C++回调函数(2)--实现回调机制的几种方式

(1)Callback方式 Callback的本质是设置一个函数指针进去,然后在需要需要触发某个事件时调用该方法, 比如Windows的窗口消息处理函数就是这种类型。比如下面的示例代码,我们在Download完成时需要触发一个通知外面的事件:#include <iostream>typedef void (__stdcall *DownloadCallback)(const char *pURL,

KingW 5357

非技术面试题精选大全

回答提示:一般人回答这个问题过于平常,只说姓名、年龄、爱好、工作经验,这些在简历上都有,其实,企业最希望知道的是求职者能否胜任工作,包括:最强的技能、最深入研究的知识领域、个性中最积极的部分、做过的最成功的事,主要的成就等,这些都可以和学习无关,也可以和学习有关,但要突出积极的个性和做事的能力,说得合情合理企业才会相信。企业喜欢有礼貌的求职者。

吃面爱放香菜的博客 434

学Simulink--基础微电网场景实例:基于Simulink的微电网并网/孤岛无缝切换控制仿真

本文完成了基于 Simulink 的微电网并网/孤岛无缝切换控制仿真,实现了:✅ 构建含双模式逆变器的微电网模型✅ 实现预同步 + Stateflow 逻辑的智能切换✅ 验证计划与非计划切换的性能边界✅ 证明“无缝”在工程上是可实现的。

amy_mhd的博客 101

C++实现回调(一)

C++实现回调(一)

cangqiongxiaoye的博客 798

基于AI的智能开发环境—Trae在Web开发中的应用实战与性能评估【Trae项目实战】

Trae 是一款与 AI 深度集成的开发工具,提供智能问答、代码自动补全和基于 Agent 的 AI 自动编程能力,极大提升开发效率。它具备完备的 IDE 功能,如代码编写、项目管理和源代码管理等,同时还具备强大的 AI 助手,能够提供智能问答、实时代码建议、代码片段生成等服务。开发者可以通过自然语言与 AI 协作,从 0 到 1 开发项目,AI 会根据需求自动生成代码或创建文件。

一键难忘的博客 3万+

C++中回调函数详解

回调函数是无数实际项目中解耦模块、实现异步处理、构建事件驱动架构的核心基石。回调函数允许将一段可执行的代码(函数)像数据一样传递给其他模块。接收方模块可以在其认为合适的时机——通常是某个特定事件(如按钮点击、数据到达、定时器到期)发生后——“回调”我们预先提供的这段代码。这种机制赋予了软件极大的灵活性:通用模块负责“何时”触发,而专用模块则负责“做什么”,两者各司其职,互不干扰。

qq_44846784的博客 993

【调优】OpenClaw从零开始高阶调优之skill篇

本文详细解析了OpenClaw技能系统的核心机制。首先介绍了技能的分层加载逻辑,按照优先级从高到低依次为:工作区专属技能、全局共享技能、出厂自带技能和自定义路径技能。通过流程图展示了从扫描到注册的完整加载流程,并解释了同名技能覆盖规则。随后深入剖析了SKILL.md文件结构,包含YAML元数据定义技能属性和Markdown正文说明使用方法,以公众号写作技能为例展示了具体配置。文章还提供了技能优先级切换的实用技巧,帮助用户灵活管理不同版本的技能。

海兰 238

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

C++ 【回调函数】详解与代码解读

在现代软件开发中,回调函数是一个常用的工具,能够实现函数调用的延迟绑定,广泛应用于事件驱动、异步操作以及模块解耦等场景。本文将从基础概念、分类、实现方式到代码示例,全面讲解 C++ 回调函数的实现和应用。

专注于 Qt/C++ 应用开发和机器视觉领域的开源项目分享。期待与您共同进步! 3480

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

简单的c++回调函数设计方法

来自:http://blog.youkuaiyun.com/water_core/article/details/4563031 简单的c++回调函数实现办法:     最近为公司升级schematic编辑器,GUI部分采用QT来实现,为了防止GUI采用的开发库的变化,决定采用 GUI

ax614的专栏 758

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

C++中实现回调机制的几种方式

转自:http://www.cnblogs.com/weiym/archive/2012/08/28/2660053.html (1)Callback方式 Callback的本质是设置一个函数指针进去,然后在需要需要触发某个事件时调用该方法, 比如Windows的窗口消息处理函数就是这种类型。 比如下面的示例代码,我们在Download完成时需要触发一个通知外面的事件: typed

尺树寸泓 534

C++回调函数使用心得

C++回调函数使用心得前言回调函数也是普通函数C回调函数C++回调函数使用场景描述C++回调函数定义静态成员函数访问非静态成员函数的方法回调对象更复杂的讨论 前言 关于C++回调函数的介绍网上有很多,要知道它的概念很容易,难的是灵活应用,这里就笔者遇到的一个使用场景对回调函数进行一个简单的介绍,如果能对您有所帮助是我的荣幸。本文不会对C++回调函数的基础知识做过多的介绍,若对其概念不够理解的,笔者...

sinat_38183777的博客 2万+

C++实现回调函数

一、定义 回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。 回调函数机制: 1、定义一个函数(普通函数即可); 2、将此函数的地址注册给调用者; 3、特定的事件或条件发生时,调用者使用函数指针调用回调函数 实例一 #include <stdio.h> typedef in

sinat_31608641的博客 6010

C++回调函数

首先看一下回调函数的官方解释:回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。这段解释比较官方。个人可以简单的理解为:**一个通过函数指针调用的函数。

zzw3354353337的博客 6591

C/C++ - 回调函数的实现

文章目录函数指针C++虚函数bink & function参考鸣谢 项目中有时候能遇到一些回调函数,于是思考其实现方法,顺便找了一下其他实现方法,简单总结一下: 函数指针 关于函数指针,有趣的是: Why do function pointer definitions work with any number of ampersands ‘&’ or asterisks ‘*’? 下面直接看 demo,这里模拟的是外部 lib 及使用的的使用方法: //CallBack 1 /******

Hsy的博客 1423

浅议C++回调函数的实现方式

引子-模板方法模式的实现 看一下设计模式中模板方法模式的实现方式,首先定义一个模板基类,它有一个模板成员函数和一个钩子成员函数: class TemplateBase { int data; // 假设有一个int型的数据成员 public: virtual ~TemplateBase() {} void process() { // 模板函数 // 其它准备操作 hook(); // 其它后续操作 } virtual void hook() {} // 钩子函数 // 其它

moter的专栏 1861

c++ 中类成员函数做回调函数的几种方式

程序实现方式是多种多样的,重要的是本质的理解。见分析小节。↩︎。

pernl的博客 2658
上一篇: 一次内存紧缩
evilcode
博客等级 码龄20年 307粉丝 16原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值