当前位置: 首页 > news >正文

『 C++ 』中理解回调类型在 C++ 中的使用方式。

文章目录

      • 案例 1:图形绘制库中的回调使用
        • 场景说明
        • 代码实现
        • 代码解释
      • 案例 2:网络服务器中的连接和消息处理回调
        • 场景说明
        • 代码实现
        • 代码解释
      • 案例 3:定时器中的回调使用
        • 场景说明
        • 代码实现
        • 代码解释


以下将通过不同场景给出几个使用回调类型的具体案例,帮助你理解回调类型在 C++ 中的使用方式。我在这里掉进一个坑,一直以为调用回调函数时,是在调用回调fction构造回调类型函数类型,就一直在下为什么他在这里只传入了类的指针(虽然类有成员方法,但是它知道调用哪个吗?)。后面发现在main函数调用回调函数时,才发现这里传入的是类外面,重新创建的回调函数。(可以不用看😂)
这里的声明的类型例如:using DrawCompleteCallback = std::function<void()>; ,它仅仅只是一个类型,方便类中方法的参数定义,后面定义的回调函数才是真正作为回调函数要调用,并且可以使用回调类型的方法。

案例 1:图形绘制库中的回调使用

场景说明

假设你正在开发一个简单的图形绘制库,当图形绘制完成后,需要通知调用者执行一些额外操作,比如记录日志或者更新界面状态。这时就可以使用回调函数来实现这种通知机制。

代码实现
#include <iostream>
#include <functional>// 定义绘制完成的回调类型
using DrawCompleteCallback = std::function<void()>;// 图形类
class Shape {
public:void draw(DrawCompleteCallback callback) {std::cout << "Drawing the shape..." << std::endl;// 模拟绘制过程for (int i = 0; i < 1000000; ++i) {}std::cout << "Shape drawn." << std::endl;// 绘制完成后调用回调函数if (callback) {callback();}}
};// 日志记录函数,作为回调函数
void logDrawCompletion() {std::cout << "Logging: Shape drawing is completed." << std::endl;
}int main() {Shape shape;// 使用日志记录函数作为回调shape.draw(logDrawCompletion);return 0;
}
代码解释
  1. 回调类型定义DrawCompleteCallback 是一个不接受任何参数且返回值为 void 的可调用对象类型。
  2. Shapedraw 方法接受一个 DrawCompleteCallback 类型的参数,在图形绘制完成后调用该回调函数。
  3. 回调函数实现logDrawCompletion 是一个普通函数,作为回调函数用于记录图形绘制完成的日志。
  4. 主函数调用:在 main 函数中,创建 Shape 对象并调用 draw 方法,传入 logDrawCompletion 作为回调函数。

案例 2:网络服务器中的连接和消息处理回调

场景说明

在一个简单的网络服务器中,需要处理新连接的建立、连接关闭以及接收到消息等事件。可以使用回调函数来处理这些事件。

代码实现
#include <iostream>
#include <memory>
#include <functional>// 假设的连接类和消息类
class BaseMessage {
public:using ptr = std::shared_ptr<BaseMessage>;
};class BaseConnection {
public:using ptr = std::shared_ptr<BaseConnection>;
};// 定义回调类型
using ConnectionCallback = std::function<void(const BaseConnection::ptr&)>;
using CloseCallback = std::function<void(const BaseConnection::ptr&)>;
using MessageCallback = std::function<void(const BaseConnection::ptr&, BaseMessage::ptr&)>;// 服务器类
class Server {
public:void setConnectionCallback(const ConnectionCallback& cb) {connectionCallback = cb;}void setCloseCallback(const CloseCallback& cb) {closeCallback = cb;}void setMessageCallback(const MessageCallback& cb) {messageCallback = cb;}// 模拟新连接事件void simulateNewConnection() {BaseConnection::ptr conn = std::make_shared<BaseConnection>();if (connectionCallback) {connectionCallback(conn);}}// 模拟连接关闭事件void simulateConnectionClose() {BaseConnection::ptr conn = std::make_shared<BaseConnection>();if (closeCallback) {closeCallback(conn);}}// 模拟接收到消息事件void simulateMessageReceived() {BaseConnection::ptr conn = std::make_shared<BaseConnection>();BaseMessage::ptr msg = std::make_shared<BaseMessage>();if (messageCallback) {messageCallback(conn, msg);}}private:ConnectionCallback connectionCallback;CloseCallback closeCallback;MessageCallback messageCallback;
};// 处理新连接的回调函数
void handleNewConnection(const BaseConnection::ptr& conn) {std::cout << "New connection established." << std::endl;
}// 处理连接关闭的回调函数
void handleConnectionClose(const BaseConnection::ptr& conn) {std::cout << "Connection closed." << std::endl;
}// 处理接收到消息的回调函数
void handleMessageReceived(const BaseConnection::ptr& conn, BaseMessage::ptr& msg) {std::cout << "Message received on connection." << std::endl;
}int main() {Server server;// 设置回调函数server.setConnectionCallback(handleNewConnection);server.setCloseCallback(handleConnectionClose);server.setMessageCallback(handleMessageReceived);// 模拟事件server.simulateNewConnection();server.simulateMessageReceived();server.simulateConnectionClose();return 0;
}
代码解释
  1. 回调类型定义:定义了 ConnectionCallbackCloseCallbackMessageCallback 三种回调类型,分别用于处理新连接建立、连接关闭和接收到消息事件。
  2. Server:提供了设置回调函数的方法,并模拟了三种事件的发生,在事件发生时调用相应的回调函数。
  3. 回调函数实现:分别实现了处理新连接、连接关闭和接收到消息的回调函数。
  4. 主函数调用:在 main 函数中,创建 Server 对象,设置回调函数,并模拟三种事件的发生。

案例 3:定时器中的回调使用

场景说明

实现一个简单的定时器类,当定时器超时后,执行指定的回调函数。

代码实现
#include <iostream>
#include <functional>
#include <thread>
#include <chrono>// 定义定时器回调类型
using TimerCallback = std::function<void()>;// 定时器类
class Timer {
public:void start(int seconds, TimerCallback callback) {std::thread([seconds, callback]() {std::this_thread::sleep_for(std::chrono::seconds(seconds));if (callback) {callback();}}).detach();}
};// 定时器超时后的回调函数
void onTimerExpired() {std::cout << "Timer expired!" << std::endl;
}int main() {Timer timer;// 启动定时器,设置超时时间为 3 秒,并传入回调函数timer.start(3, onTimerExpired);std::cout << "Timer started. Waiting for expiration..." << std::endl;// 为了避免主线程提前退出,让主线程休眠一段时间std::this_thread::sleep_for(std::chrono::seconds(5));return 0;
}
代码解释
  1. 回调类型定义TimerCallback 是一个不接受任何参数且返回值为 void 的可调用对象类型。
  2. Timerstart 方法接受一个超时时间(秒)和一个 TimerCallback 类型的回调函数,启动一个新线程,在指定的超时时间后调用回调函数。
  3. 回调函数实现onTimerExpired 是一个普通函数,作为定时器超时后的回调函数,输出提示信息。
  4. 主函数调用:在 main 函数中,创建 Timer 对象,启动定时器并传入 onTimerExpired 作为回调函数。

通过以上案例,你可以看到回调类型在不同场景下的使用方式,其核心思想是将一个可调用对象作为参数传递给某个函数或类,在特定事件发生时调用该可调用对象。

相关文章:

『 C++ 』中理解回调类型在 C++ 中的使用方式。

文章目录 案例 1&#xff1a;图形绘制库中的回调使用场景说明代码实现代码解释 案例 2&#xff1a;网络服务器中的连接和消息处理回调场景说明代码实现代码解释 案例 3&#xff1a;定时器中的回调使用场景说明代码实现代码解释 以下将通过不同场景给出几个使用回调类型的具体案…...

git多人协作

目录 一、项目克隆 二、 1、进入克隆仓库设置 2、协作处理 3、冲突处理 4、多人协作分支的推送拉取删除 1、分支推送&#xff08;2种&#xff09; 2、远程分支拉取&#xff08;2种&#xff09; 3、远程分支删除 一、项目克隆 git clone 画船听雨眠/test1 (自定义的名…...

CTFSHOW-WEB入门-命令执行71-77

题目&#xff1a;web 71 题目&#xff1a;解题思路&#xff1a;分析可知highlight_file() 函数被禁了&#xff0c;先想办法看看根目录&#xff1a;cvar_export(scandir(dirname(‘/’))); 尝试一下发现很惊奇&#xff1a;&#xff08;全是&#xff1f;&#xff09;这种情况我也…...

浅谈《图解HTTP》

感悟 滑至尾页的那一刻&#xff0c;内心突兀的涌来一阵畅快的感觉。如果说从前对互联网只是懵懵懂懂&#xff0c;但此刻却觉得她是如此清晰而可爱的呈现在哪里。 介绍中说&#xff0c;《图解HTTP》适合作为第一本网络协议书。确实&#xff0c;它就像一座桥梁&#xff0c;连接…...

LLMs瞬间获得视觉与听觉感知,无需专门训练:Meta的创新——在图像、音频和视频任务上实现最优性能。

引言&#xff1a; 问题&#xff1a; 当前的多模态任务&#xff08;如图像、视频、音频描述生成、编辑、生成等&#xff09;通常需要针对特定任务训练专门的模型&#xff0c;而现有的方法在跨模态泛化方面存在局限性&#xff0c;难以适应新任务。此外&#xff0c;多模态嵌入反演…...

自研有限元软件与ANSYS精度对比-Bar3D2Node三维杆单元模型-央视大裤衩实例

目录 1、“央视大裤衩”自研有限元软件求解 1.1、选择单元类型 1.2、导入“央视大裤衩”工程 1.3、节点坐标定义 1.4、单元连接关系、材料定义 1.5、约束定义 1.6、外载定义 1.7、矩阵求解 1.8、变形云图展示 1.9、节点位移 1.10、单元应力 1.11、节点支反力 2、“…...

kubernetes 高可用集群搭建

在生产环境中部署 Kubernetes 集群时&#xff0c;确保其高可用性&#xff08;High Availability, HA&#xff09;是至关重要的。高可用性不仅意味着减少服务中断时间&#xff0c;还能提高系统的稳定性和可靠性。本文将详细介绍如何搭建一个高可用的 Kubernetes 集群&#xff0c…...

【C++】STL——vector底层实现

目录 &#x1f495; 1.vector三个核心 &#x1f495;2.begin函数&#xff0c;end函数的实现&#xff08;简单略讲&#xff09; &#x1f495;3.size函数&#xff0c;capacity函数的实现 &#xff08;简单略讲&#xff09; &#x1f495;4.reserve函数实现 &#xff08;细节…...

数据结构初探:链表之单链表篇

本文图皆为作者手绘,所有代码基于vs2022运行测试 系列文章目录 数据结构初探:顺序表篇 文章目录 系列文章目录前言一、链表基础概念二、链表的分类简化边界条件处理使代码更清晰简洁提高程序稳定性 1.单链表(不带头不循环的单链表);1.1存储结构;1.2准备工作1.3链表增删查改的实…...

介绍一下Mybatis的底层原理(包括一二级缓存)

表面上我们的就是Sql语句和我们的java对象进行映射&#xff0c;然后Mapper代理然后调用方法来操作数据库 底层的话我们就涉及到Sqlsession和Configuration 首先说一下SqlSession&#xff0c; 它可以被视为与数据库交互的一个会话&#xff0c;用于执行 SQL 语句&#xff08;Ex…...

Linux基础 ——tmux vim 以及基本的shell语法

Linux 基础 ACWING y总的Linux基础课&#xff0c;看讲义作作笔记。 tmux tmux 可以干嘛&#xff1f; tmux可以分屏多开窗口&#xff0c;可以进行多个任务&#xff0c;断线&#xff0c;不会自动杀掉正在进行的进程。 tmux – session(会话&#xff0c;多个) – window(多个…...

64位的谷歌浏览器Chrome/Google Chrome

64位的谷歌浏览器Chrome/Google Chrome 在百度搜索关键字:chrome&#xff0c;即可下载官方的“谷歌浏览器Chrome/Google Chrome”&#xff0c;但它可能是32位的&#xff08;切记注意网址&#xff1a;https://www.google.cn/....&#xff0c; 即&#xff1a;google.cn&#xff…...

jetson编译torchvision出现 No such file or directory: ‘:/usr/local/cuda/bin/nvcc‘

文章目录 1. 完整报错2. 解决方法 1. 完整报错 jetson编译torchvision,执行python3 setup.py install --user遇到报错 running build_ext error: [Errno 2] No such file or directory: :/usr/local/cuda/bin/nvcc完整报错信息如下&#xff1a; (pytorch) nxnx-desktop:~/Do…...

多线程创建方式三:实现Callable接口

实现Callable第三种方式存在的原因 作用&#xff1a;可以返回线程执行完毕后的结果。 前两种线程创建方式都存在的一个问题&#xff1a;假如线程执行完毕后有一些数据需要返回,他们重写的run方法均不能直接返回结果。 如何实现 ● JDK 5.0提供了Callable接口和FutureTask类来…...

Linux下的编辑器 —— vim

目录 1.什么是vim 2.vim的模式 认识常用的三种模式 三种模式之间的切换 命令模式和插入模式的转化 命令模式和底行模式的转化 插入模式和底行模式的转化 3.命令模式下的命令集 光标移动相关的命令 复制粘贴相关命令 撤销删除相关命令 查找相关命令 批量化注释和去…...

Docker技术相关学习二

一、Docker简介 1.Docker之父Solomon Hykes形容docker就像传统的货运集装箱。 2.docker的特点和优势&#xff1a; 轻量级虚拟化&#xff1a;Docker容器相较于传统的虚拟机更加的轻量和高效&#xff0c;能够快速的启动和停止来节省系统资源。 一致性&#xff1a;确保应用程序在不…...

【人工智能】多模态学习在Python中的应用:结合图像与文本数据的深度探索

《Python OpenCV从菜鸟到高手》带你进入图像处理与计算机视觉的大门! 解锁Python编程的无限可能:《奇妙的Python》带你漫游代码世界 多模态学习是人工智能领域的一个重要研究方向,旨在通过结合多种类型的数据(如图像、文本、音频等)来提高模型的性能。本文将深入探讨多模…...

【MySQL】常用语句

目录 1. 数据库操作2. 表操作3. 数据操作&#xff08;CRUD&#xff09;4. 高级查询5. 索引管理6. 用户与权限7. 数据导入导出8. 事务控制9. 其他实用语句注意事项 如果这篇文章对你有所帮助&#xff0c;渴望获得你的一个点赞&#xff01; 1. 数据库操作 创建数据库 CREATE DATA…...

Docker网络基础

一、Docker网络基础 1.docker安装后会自动创建3中网络&#xff0c;分别为bridge host none docker network ls 2.docker原生bridge网络&#xff1a; docker安装时会创建一个名为docker0的linux bridge,新建的容器会自动桥接到这个接口 bridge模式下没有公有ip,只有宿主机可以…...

重新刷题求职2-DAY2

977. 有序数组的平方 给你一个按 非递减顺序 排序的整数数组 nums&#xff0c;返回 每个数字的平方 组成的新数组&#xff0c;要求也按 非递减顺序 排序。 示例 1&#xff1a; 输入&#xff1a;nums [-4,-1,0,3,10] 输出&#xff1a;[0,1,9,16,100] 解释&#xff1a;平方后…...

后进先出(LIFO)详解

LIFO 是 Last In, First Out 的缩写&#xff0c;中文译为后进先出。这是一种数据结构的工作原则&#xff0c;类似于一摞盘子或一叠书本&#xff1a; 最后放进去的元素最先出来 -想象往筒状容器里放盘子&#xff1a; &#xff08;1&#xff09;你放进的最后一个盘子&#xff08…...

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造&#xff0c;完美适配AGV和无人叉车。同时&#xff0c;集成以太网与语音合成技术&#xff0c;为各类高级系统&#xff08;如MES、调度系统、库位管理、立库等&#xff09;提供高效便捷的语音交互体验。 L…...

(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)

题目&#xff1a;3442. 奇偶频次间的最大差值 I 思路 &#xff1a;哈希&#xff0c;时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况&#xff0c;哈希表这里用数组即可实现。 C版本&#xff1a; class Solution { public:int maxDifference(string s) {int a[26]…...

java调用dll出现unsatisfiedLinkError以及JNA和JNI的区别

UnsatisfiedLinkError 在对接硬件设备中&#xff0c;我们会遇到使用 java 调用 dll文件 的情况&#xff0c;此时大概率出现UnsatisfiedLinkError链接错误&#xff0c;原因可能有如下几种 类名错误包名错误方法名参数错误使用 JNI 协议调用&#xff0c;结果 dll 未实现 JNI 协…...

电脑插入多块移动硬盘后经常出现卡顿和蓝屏

当电脑在插入多块移动硬盘后频繁出现卡顿和蓝屏问题时&#xff0c;可能涉及硬件资源冲突、驱动兼容性、供电不足或系统设置等多方面原因。以下是逐步排查和解决方案&#xff1a; 1. 检查电源供电问题 问题原因&#xff1a;多块移动硬盘同时运行可能导致USB接口供电不足&#x…...

什么是库存周转?如何用进销存系统提高库存周转率?

你可能听说过这样一句话&#xff1a; “利润不是赚出来的&#xff0c;是管出来的。” 尤其是在制造业、批发零售、电商这类“货堆成山”的行业&#xff0c;很多企业看着销售不错&#xff0c;账上却没钱、利润也不见了&#xff0c;一翻库存才发现&#xff1a; 一堆卖不动的旧货…...

学习STC51单片机32(芯片为STC89C52RCRC)OLED显示屏2

每日一言 今天的每一份坚持&#xff0c;都是在为未来积攒底气。 案例&#xff1a;OLED显示一个A 这边观察到一个点&#xff0c;怎么雪花了就是都是乱七八糟的占满了屏幕。。 解释 &#xff1a; 如果代码里信号切换太快&#xff08;比如 SDA 刚变&#xff0c;SCL 立刻变&#…...

微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据

微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据 Power Query 具有大量专门帮助您清理和准备数据以供分析的功能。 您将了解如何简化复杂模型、更改数据类型、重命名对象和透视数据。 您还将了解如何分析列&#xff0c;以便知晓哪些列包含有价值的数据&#xff0c;…...

推荐 github 项目:GeminiImageApp(图片生成方向,可以做一定的素材)

推荐 github 项目:GeminiImageApp(图片生成方向&#xff0c;可以做一定的素材) 这个项目能干嘛? 使用 gemini 2.0 的 api 和 google 其他的 api 来做衍生处理 简化和优化了文生图和图生图的行为(我的最主要) 并且有一些目标检测和切割(我用不到) 视频和 imagefx 因为没 a…...

探索Selenium:自动化测试的神奇钥匙

目录 一、Selenium 是什么1.1 定义与概念1.2 发展历程1.3 功能概述 二、Selenium 工作原理剖析2.1 架构组成2.2 工作流程2.3 通信机制 三、Selenium 的优势3.1 跨浏览器与平台支持3.2 丰富的语言支持3.3 强大的社区支持 四、Selenium 的应用场景4.1 Web 应用自动化测试4.2 数据…...