从C++类成员函数作为回调函数说起

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

在网络消息处理中经常要用到回调机制。

例如处理异步网络操作的前摄器设计模式(Proactor),(可以参考 《C++ 网络编程 卷2》中关于ACE Proactor模式实现 )。

异步的 Web 服务器将这样来利用前摄器模式:首先让 Web 服务器向 OS 发出异步操作,并将回调方法登记到 Completion Dispatcher(完成分派器),后者将在操作完成时通知 Web 服务器。于是 OS 代表 Web 服务器执行操作,并随即在一个周知的地方将结果排队。Completion Dispatcher 负责使完成通知出队,并执行适当的、含有应用特有的 Web 服务器代码的回调。

使用前摄器模式的主要优点是可以启动多个并发操作,并可并行运行,而不要求应用必须拥有多个线程。操作被应用异步地启动,它们在 OS 的 I/O 子系统中运行直到完成。发起操作的线程现在可以服务 另外的请求了。

 

在ACE中,可以通过ACE_Proactor实现前摄器模式。实现方式如下。

1。创建服务处理器:

Proactor框架中服务处理器均派生自ACE_Service_Handler,它和Reactor框架的事件处理器非常类似。当发生IO操作完成事件时,会触发相应的事件完成会调函数。

2。实现服务处理器IO操作

Proactor框架中所有的IO操作都由相应的异步操作类来完成,这些异步操作类都继承自ACE_Asynch_Operation。常用的有以下几种。

  1. ACE_Asynch_Read_Stream, 提供从TCP/IP socket连接中进行异步读操作.
  2. ACE_Asynch_Write_Stream, 提供从TCP/IP socket连接中进行异步写操作.

使用这些操作类的一般方式如下:

  1. 初始化
    将相关的操作注册到服务处理器中,一般可通过调用其open方法实现。
  2. 发出IO操作
    发出异步IO操作请求,该操作不会阻塞,具体的IO操作过程由操作系统异步完成。
  3. IO操作完成回调处理
    异步IO操作完成后,OS会触发服务处理器中的相应回调函数,可通过该函数的ACE_Asynch_Result参数获取相应的返回值。

3。使用连接器或接受器和远端进行连接

ACE为Proactor框架提供了两个工厂类来建立TCP/IP连接。

  1. ACE_Asynch_Acceptor, 用于被动地建立连接
  2. ACE_Asynch_Connector 用于主动地建立连接

当远端连接建立时,连接器或接受器便会创建相应的服务处理器,从而可以实现服务处理。

4。启动Proactor事件分发处理

启动事件分发处理只需如下调用:

    while(true)
        ACE_Proactor::instance ()->handle_events ();
  

 

本次话题的重点是 ACE_Service_Handler 如何向 ACE_Proactor 注册回调函数。

ACE的做法是利用虚函数所得到的多态性质。

ACE_Service_Handler 作为网络事件处理器的基类,它通过虚函数规范了事件处理的接口函数。在客户开发自己的网络程序时,需要写自己的事件处理器,它必须从ACE_Service_Handler 继承这些接口,并根据情况改写它们。

网络程序在连接建立时将ACE_Service_Handler的派生类实体注册到ACE_Proactor,在网络事件到达时,ACE_Proactor通过约定的接口可以将事件处理转接到已注册的ACE_Service_Handler的派生类实体。

 

上面实现的弊端是:

1. 使用继承和虚函数增大了客户程序与ACE框架的耦合性。客户程序的事件处理器必须继承自ACE_Service_Handler。众所周知继承是仅次于友元的耦合关系。

2. 用于使用继承,客户类的行为不完全可控,可能导致在资源管理时陷入两难的境地。用过ACE写过网络程序的都知道,ACE Proactor本身是一个半成熟的框架,一种情况是ACE_Service_Handler可能同时运行在ACE_Proactor所在的线程,以及另外一个发送端控制线程上,在控制线程可能发起正常连接释放,也有可能在事件处理中检测到网络故障而释放,这两种释放可能在两个不同的线程中,要做到资源没有泄露并非易事。

3. 虚函数的运行开销。

 

那么是否有一种回调机制使得事件处理器(Event Handler)不必从一个限定的基类派生,而是可以将自己符合接口定义的任一成员函数作为回调函数直接注册到完成分派器(Completion Dispatcher)。

 

在C语言中将一个全局函数用于回调非常容易。然而在C++中要将一个普通类成员函数用于回调却并非易事。原因参见我的文章http://blog.youkuaiyun.com/MPForwd/archive/2010/07/28/5772462.aspx

 

当然,时代在进步,新的技术为我们提供了完善的解决方案。从《Modern C++ Design》中的探索实践。到boost fuction 和boost bind的标准化方案,以上想法已经被很多库实现。

下面介绍一个例子,用boost function 和boost bind 来将类成员函数用于回调机制。

 

 

已知应用:boost asio使用更现代的C++的方法实现前摄式设计模式(Proactor)。可以将类成员函数通过boost bind适配为完成事件处理函数。从而解除了对公共基类的依赖。

如下是利用 boost asio 写的一个udp的例子。在这个例子中假设我们的角色是一个udp客户端。实际上从协议上看upd通信的双方是对等的。没有客户端与服务器之分。

 

 

 

 

C++中的回调函数 一、回调机制 1.回调定义(小A带着名片D通过途径C找到小B求他帮忙,小B不能立即解决于是收下名片D,之后的某天小B解决了小A的问题后又通过名片D告诉了小A解决方法) 2.回调方法: ①定义一个函数(普通函数即可);②将此函数的地址注册给调用者;③特定的事件或条件发生时,调用者使用函数指针调用回调函数。例如: 二、同步回调和异步回调 举例:假设有两个程序员在写代码,A程序员写底层... 阅读详情

相关推荐

C++中类成员函数作为回调函数

方法一:回调函数为普通函数,但在函数体内执行成员函数 见以下代码: class MyClass { pthread_t TID; public: void func() { //子线程执行代码 } bool startThread() {//启动子线程 int ret = pthread_create( &TID , NULL , callback , this ); if( ret != 0 ) return false; else return tru

我不是码农的博客~~~ 3252

c++类成员函数作回调

C++类的成员函数作回调函数,主要分三种情况: 1,类的static函数,由于此类函数属于类而非类的实例,不存在this指针的概念,因此可以直接取其函数地址作为回调; 2,类的普通成员函数,这类函数在实现上存在着隐含的this指针,因此作为回调必须指明是哪一个类实例的函数。 3,类的virtual函数,由于存在多态,如果将其作为回调函数,其逻辑上可能会比较复杂,个人觉得应该尽量避免。 以下是C++...

风居住的城市 4567

C++中成员函数如何作为回调函数

引言 C++中成员函数在一般情况下是无法作为回调函数的 原因就是因为一般的成员函数在传参时为了可以访问成员变量或者返回本身 会默认的传一个 this 指针 但是回调函数再触发时会返回参数 这就会导致在把成员函数作为回调函数的时候会报参数错误这样一种奇怪的错误 那么如何去避免这种情况呢 本文针对此种情况介绍两种方法 一.类内静态成员函数作为回调函数 我们报错的原因是因为成员函数会隐式的传一个 this 指针,但静态成员函数就不会多这一个参数 所以我们的方法就是把类内静态成员当做回调函数 但这又牵扯到一个问题 

我不是码农的博客~~~ 3482

c++类成员函数作为回调函数

一直以来都被回调函数的定义给整蒙了。最近又仔细学了会,感觉回调函数,我认为就是将一个函数指针A作为参数传入另外一个函数B,然后在函数B中调用函数A。       普通回调          具体先看一个简单的例子:          #include void printWelcome(int len) { printf("welcome -- %d\n", len);

小胡——uYou的专栏 2万+

ZedBoard+Vivado(二)——PS + PL实现流水灯

硬件:Zedboard 软件:Vivado2018.2 + Win10 本文参考了http://blog.chinaaet.com/cuter521/p/35978的设计 1 设计 功能:PS + PL流水灯 语言:C 流程:创建工程-&amp;gt;IP Integrator-&amp;gt;综合、实现、生成Bitstream-&amp;gt;SDK 2 流程 2.1 创建工程 跟上一篇步骤完全相同,这里不用添加源文...

q416524389的博客 3695

C++利用spdlog生成日志

C++利用spdlog生成日志下载编译spdlog配置并使用 环境:Win10-x64+VS2015 spdlog是一个快速的C++日志库,能够兼容C++11,具备快速、无需依赖第三方库、支持多线程、多平台的优良特性! 下载编译spdlog 1.第一步,下载spdlog 下载spdlog,下载地址:https://github.com/gabime/spdlog#header-only-version,从Github上下载zip压缩包。下载完成后会获取一个名为spdlog-1.x.zip的压缩包 2.第二步

weixin_42975610的博客 3222

C++类成员函数指针使用介绍

前言 在之前写过的博客中有介绍过函数指针和指针函数的区别和简单用法(文章在这里),当时的Demo非常简单,都是C语言的写法,但是当在C++中直接像C那样使用类成员函数指针时就会报错:reference to non-static member function must be called 所以如果是C++中的成员函数指针其使用方法是有区别的,这里针对不同的场景做个补充说明。 类成员函数的指针(非...

luoyayun361的专栏 2万+

阿里系acw_sc__v3滑块验证码逆向分析与实战破解

本文深入解析阿里系acw_sc__v3滑块验证码的核心机制与逆向破解方法。通过分析加密参数生成、轨迹验证模块和动态加密策略,提供完整的自动化破解方案,包括设备指纹生成、缺口识别和轨迹加密等关键技术。文章还分享了常见问题的调试技巧,帮助开发者应对阿里系验证码的复杂防护体系。

wdx012345的博客 1832

C++中的回调函数——指向类成员的指针

C++中的回调函数   ——指向类成员的指针 在C中我们能够很容易地实现一个指向函数的指针,因此能够方便地实现函数的回调机制。但是在C++中很多人认为类的成员函数不能作为回调函数,因此很多C程序不能移植到C++上来。其实不是这样的,在C++中我们同样可以获取类的成员函数的指针,也能方便地实现函数回调机制。 下面先数一下C/C++中普通函数作为回调函数的情况,然后再说C++ 中类成员函

doufei_JLU_CCST_08 8145

Unity2D像素刀光实现:粒子方向控制与像素级渲染规范

像素风游戏中的刀光特效并非普通粒子动画,而是需严格遵循像素艺术原理的视觉暂留模拟。其核心在于将‘瞬时切割感’转化为程序可执行的渲染逻辑:通过禁用纹理滤波保障1:1像素锐度,绑定刀锋向量控制粒子运动方向,限定≤0.15秒生命周期匹配人眼暂留阈值,并采用Stretched Billboard实现动态拉伸拖影。该方案兼顾美术语义(如直劈、横扫、突刺)与工程约束(Sorting Layer分层、对象池复用、单粒子GPU优化),广泛适用于Unity2D平台的动作反馈系统,尤其适配《空洞骑士》《死亡细胞》类高节奏像素R

weixin_32390647的博客 283

电力现货市场出清机制解析:从理论到实践(附节点电价计算实例)

本文深入解析电力现货市场的核心出清机制,重点阐述了节点边际电价的计算原理与实践方法。通过对比系统边际电价、节点边际电价和分区边际电价三种模式,揭示了市场出清价格如何反映电力供需与网络阻塞。文章结合IEEE 30节点系统,提供了基于MATLAB和最优潮流模型的计算实例,详细展示了从构建模型到求解对偶变量以获取节点电价的全过程,为理解电力市场定价机制提供了从理论到实践的完整路径。

whisky的博客 757

C++类成员函数作回调函数

C++类成员函数作回调函数,示例:C++消息注册派发模式

木可的博客 4985

【用unity实现100个游戏之34】使用环状(车轮)碰撞器(Wheel Collider)从零实现一个汽车车辆物理控制系统,实现一个赛车游戏

本文介绍了在Unity中使用Wheel Collider组件实现3D车辆物理控制系统的详细步骤。主要内容包括: Wheel Collider参数详解:包括基础参数(质量、半径等)、悬挂弹簧系统(弹力、减震等)和摩擦力设置(前向/侧向摩擦曲线)。 准备工作流程: 导入赛车模型、赛道和树木素材 为车身添加Rigidbody和MeshCollider 创建四个Wheel Collider并调整参数(半径、悬挂距离等) 优化摩擦系数设置防止侧滑 实现车辆控制: 通过代码控制车轮前后移动和转向 提供底盘系统设置(四轮

向宇的博客,专注php/web全栈 unity游戏开发,欢迎大家评论纠错 2658

C++类成员函数作为回调函数的实现与实践

摘要 C++中实现类成员函数作为回调函数面临的核心挑战是:非静态成员函数隐含this指针导致与普通函数指针类型不兼容。本文介绍了三种主要解决方案: 静态成员函数+实例指针:通过静态函数作为中介,传递实例指针实现回调,兼容C语言接口但代码较繁琐。 std::function+std::bind:利用C++11的可调用对象包装器和绑定器,无需静态函数,保持封装性且灵活性强。 Lambda表达式捕获:通过Lambda捕获类实例,简洁地包装成员函数调用,是现代C++最推荐的方式。 这些方法各有适用场景,开发者可根据

bkspiderx的博客 1164

【WorkBuddy从入门到精通实战教程】第 4 章 快速完成第一个 WorkBuddy 任务

摘要:WorkBuddy任务创建指南详细说明了从新建任务到结果验收的全流程。操作步骤包括:选择工作目录、设置模式(Craft/Ask/Plan)、指定AI模型、输入任务说明(需包含目标/输入/动作/约束/输出/验收6要素),可选配Skill等高级设置。文中提供三个入门示例:A)文件整理需保持原文件并生成分类方案;B)会议纪要要求结构化输出且所有内容有原文依据;C)Word转PPT需遵循品牌规范并控制页数。特别强调首次操作应在演练目录测试,处理真实数据前需确认授权范围,输出文件需检查涉密信息并按规范共享。(1

企鹅码农的专属播客,分享10多年的实战案例和经验解读,包含YOLO、RT-DETR、AI等各个工作领域。 1348

Python 爬虫实战:全球咖啡期货市场数据采集与分析全攻略

通过本项目,我们实现了对全球咖啡期货市场数据的采集、处理和可视化,为市场分析和决策支持提供了数据基础。未来,可以进一步结合机器学习和深度学习技术,对咖啡期货价格进行预测和建模,提高市场分析的准确性和效率。

2201_76125261的博客 395

类成员函数作为回调函数的方法及注意点

编程中遇到一个错误,提示为error C2597: illegal reference to non-static member 即因为一个类的静态成员函数调用了类的非静态成员变量,而报错。 下面具体介绍一些相关知识点,以防下次再出错。 类成员函数当回调函数的方法 参考自:https://blog.youkuaiyun.com/this_capslock/article/details/1700100...

hanxiucaolss的博客 1万+

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

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

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

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

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

C++ 中回调函数的实现方式-类成员函数作为回调

MyClass首先,定义了一个MyClass类,里面包含一个成员函数和一个普通成员函数。public:// 类成员函数,作为回调函数// 接收回调函数并调用的函数成员函数:这是一个回调函数,它接受一个int参数并输出该值。成员函数:它接收一个类型的回调函数,并在内部调用该回调函数,传递一个整数value。

lqq 1582

C++中类成员函数作为回调函数的几种方法

写了一个C++小游戏,想法是间接别人的C语言,但是真正自己操作起来,还是会遇到各种问题,同时也让自己更真切的学到了一些过眼即忘,只有亲自动手才能学到的知识。

lmdyyh5722756的专栏 6659

C++中 线程函数为静态函数 及 类成员函数作为回调函数(转载)

C++中 线程函数为静态函数 及 类成员函数作为回调函数 线程函数为静态函数: 线程控制函数和是不是静态函数没关系,静态函数是在构造中分配的地址空间,只有在析构时才释放也就是全局的东西,不管线程是否运行,静态函数的地址是不变的,并不在线程堆栈中static只是起了一个装饰的作用,所以二者并没有必然的关系 线程也是一种资源,是受系统调度的。因此,你必须要让系统知道你的线程的起始位置,即线程函数的指针。Window系统的接口(API)是C标准的,系统在启动线程时,需要直接得到线程的起始位置,因此你也必须向系统直

Garden的博客 1271

C++实现回调函数

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

sinat_31608641的博客 6010
上一篇: C++工厂模式实现与改进小结
下一篇: Boost.Asio和ACE之间关于Socket编程的比较
MPForwd
博客等级 码龄20年 7粉丝 20原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值