当前位置: 首页 > 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;平方后…...

如何在看板中有效管理突发紧急任务

在看板中有效管理突发紧急任务需要&#xff1a;设立专门的紧急任务通道、重新调整任务优先级、保持适度的WIP&#xff08;Work-in-Progress&#xff09;弹性、优化任务处理流程、提高团队应对突发情况的敏捷性。其中&#xff0c;设立专门的紧急任务通道尤为重要&#xff0c;这能…...

04-初识css

一、css样式引入 1.1.内部样式 <div style"width: 100px;"></div>1.2.外部样式 1.2.1.外部样式1 <style>.aa {width: 100px;} </style> <div class"aa"></div>1.2.2.外部样式2 <!-- rel内表面引入的是style样…...

涂鸦T5AI手搓语音、emoji、otto机器人从入门到实战

“&#x1f916;手搓TuyaAI语音指令 &#x1f60d;秒变表情包大师&#xff0c;让萌系Otto机器人&#x1f525;玩出智能新花样&#xff01;开整&#xff01;” &#x1f916; Otto机器人 → 直接点明主体 手搓TuyaAI语音 → 强调 自主编程/自定义 语音控制&#xff08;TuyaAI…...

css3笔记 (1) 自用

outline: none 用于移除元素获得焦点时默认的轮廓线 broder:0 用于移除边框 font-size&#xff1a;0 用于设置字体不显示 list-style: none 消除<li> 标签默认样式 margin: xx auto 版心居中 width:100% 通栏 vertical-align 作用于行内元素 / 表格单元格&#xff…...

3-11单元格区域边界定位(End属性)学习笔记

返回一个Range 对象&#xff0c;只读。该对象代表包含源区域的区域上端下端左端右端的最后一个单元格。等同于按键 End 向上键(End(xlUp))、End向下键(End(xlDown))、End向左键(End(xlToLeft)End向右键(End(xlToRight)) 注意&#xff1a;它移动的位置必须是相连的有内容的单元格…...

有限自动机到正规文法转换器v1.0

1 项目简介 这是一个功能强大的有限自动机&#xff08;Finite Automaton, FA&#xff09;到正规文法&#xff08;Regular Grammar&#xff09;转换器&#xff0c;它配备了一个直观且完整的图形用户界面&#xff0c;使用户能够轻松地进行操作和观察。该程序基于编译原理中的经典…...

基于matlab策略迭代和值迭代法的动态规划

经典的基于策略迭代和值迭代法的动态规划matlab代码&#xff0c;实现机器人的最优运输 Dynamic-Programming-master/Environment.pdf , 104724 Dynamic-Programming-master/README.md , 506 Dynamic-Programming-master/generalizedPolicyIteration.m , 1970 Dynamic-Programm…...

ip子接口配置及删除

配置永久生效的子接口&#xff0c;2个IP 都可以登录你这一台服务器。重启不失效。 永久的 [应用] vi /etc/sysconfig/network-scripts/ifcfg-eth0修改文件内内容 TYPE"Ethernet" BOOTPROTO"none" NAME"eth0" DEVICE"eth0" ONBOOT&q…...

Python 包管理器 uv 介绍

Python 包管理器 uv 全面介绍 uv 是由 Astral&#xff08;热门工具 Ruff 的开发者&#xff09;推出的下一代高性能 Python 包管理器和构建工具&#xff0c;用 Rust 编写。它旨在解决传统工具&#xff08;如 pip、virtualenv、pip-tools&#xff09;的性能瓶颈&#xff0c;同时…...

Golang——6、指针和结构体

指针和结构体 1、指针1.1、指针地址和指针类型1.2、指针取值1.3、new和make 2、结构体2.1、type关键字的使用2.2、结构体的定义和初始化2.3、结构体方法和接收者2.4、给任意类型添加方法2.5、结构体的匿名字段2.6、嵌套结构体2.7、嵌套匿名结构体2.8、结构体的继承 3、结构体与…...