C++回调函数以及epoll中回调函数的使用
回调函数是一种常用的编程技术,它允许程序在运行时将一个函数作为参数传递给另一个函数,以实现更加灵活和可扩展的功能。在C++中,回调函数通常被实现为函数指针或者函数对象。
函数指针是指向函数的指针变量,可以通过它来调用函数。函数对象是一种可调用对象,它是一个类的对象,其中定义了一个operator()函数,可以像普通函数一样进行调用。下面是一个简单的回调函数示例,使用函数指针作为回调函数:
#include <iostream>// 定义回调函数类型
typedef void (*Callback)(int);// 回调函数
void my_callback(int x) {std::cout << "Callback function called with argument " << x << std::endl;
}// 接受回调函数作为参数的函数
void do_something(Callback callback) {// 执行某些操作int result = 42;// 调用回调函数callback(result);
}int main() {// 调用do_something函数,并传递回调函数my_callback作为参数do_something(my_callback);return 0;
}
在上面的示例中,我们定义了一个回调函数类型Callback,该类型是一个函数指针,接受一个int类型的参数并返回void。然后我们定义了一个my_callback函数,它接受一个int类型的参数,并打印出该参数的值。接着我们定义了一个do_something函数,它接受一个Callback类型的参数,并执行一些操作后调用该回调函数。
在主函数中,我们调用do_something函数,并传递my_callback函数作为参数。当do_something函数执行完成后,它会调用传递进来的回调函数my_callback,并将一个int类型的参数传递给它。
除了函数指针外,C++中还可以使用函数对象实现回调函数。下面是一个使用函数对象的回调函数示例:
#include <iostream>// 回调函数对象
class MyCallback {
public:void operator()(int x) const {std::cout << "Callback function called with argument " << x << std::endl;}
};// 接受回调函数对象作为参数的函数
void do_something(const MyCallback& callback) {// 执行某些操作int result = 42;// 调用回调函数对象callback(result);
}int main() {// 调用do_something函数,并传递回调函数对象MyCallback作为参数do_something(MyCallback());return 0;
}
在这个示例中,我们定义了一个回调函数对象MyCallback,它是一个类,其中定义了一个operator()函数,接受一个int类型的参数并返回void。我们还定义了一个do_something函数,它接受一个MyCallback类型的参数,并执行一些操作后调用该回调函数对象。
在主函数中,我们调用do_something函数,并传递MyCallback对象作为参数。当do_something函数执行完成后,它会调用传递进来的回调函数对象MyCallback,并将一个int类型的参数传递给它。
总的来说,回调函数是一种非常有用的编程技术,它可以使程序更加灵活和可扩展。通过将一个函数作为参数传递给另一个函数,我们可以在运行时动态地改变程序的行为。无论是使用函数指针还是函数对象,回调函数都是实现回调机制的常用方式。
epoll中回调函数的使用
epoll_wait函数会阻塞进程,直到有一个或多个文件描述符准备好进行读或写或者出现错误或超时。当epoll_wait返回时,程序需要通过遍历epoll_event数组来确定哪些文件描述符准备好进行读或写或者出现错误或超时,从而进行相应的处理。
在epoll_event结构体中,有一个data成员,它可以存储任意的用户数据。在epoll_wait函数中,我们可以将某个文件描述符关联的回调函数指针保存在data成员中。当epoll_wait函数返回并确定该文件描述符已准备好读或写时,程序会调用该回调函数来进行相应的处理。
以下是一个使用回调函数的epoll示例:
#include <sys/epoll.h>
#include <unistd.h>
#include <iostream>// 定义回调函数类型
typedef void (*Callback)(int);// 回调函数
void read_callback(int fd) {char buf[1024] = {0};int ret = read(fd, buf, sizeof(buf));if (ret > 0) {std::cout << "Read data from file descriptor " << fd << ": " << buf << std::endl;} else {std::cout << "Error reading data from file descriptor " << fd << std::endl;}
}// 添加文件描述符到epoll实例
void add_epoll(int epoll_fd, int fd, Callback callback) {epoll_event event;event.events = EPOLLIN;event.data.ptr = (void*)callback; // 保存回调函数指针到data成员epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fd, &event);
}int main() {int epoll_fd = epoll_create(10);int fd1 = STDIN_FILENO;int fd2 = STDOUT_FILENO;// 添加文件描述符到epoll实例add_epoll(epoll_fd, fd1, read_callback);add_epoll(epoll_fd, fd2, read_callback);// 监听文件描述符事件epoll_event events[10];while (true) {int n = epoll_wait(epoll_fd, events, sizeof(events)/sizeof(epoll_event), -1);for (int i = 0; i < n; i++) {Callback callback = (Callback)events[i].data.ptr; // 获取回调函数指针int fd = events[i].data.fd;callback(fd); // 调用回调函数进行处理}}return 0;
}
在这个示例中,我们定义了一个read_callback函数作为回调函数,用于读取文件描述符中的数据。我们还定义了一个add_epoll函数,它将一个文件描述符及其对应的回调函数添加到epoll实例中。在add_epoll函数中,我们将回调函数指针保存在epoll_event结构体的data.ptr成员中。在主函数中,我们使用epoll_wait函数监听文件描述符事件,并在事件触发时通过回调函数处理文件描述符中的数据。
需要注意的是,在使用回调函数时,必须保证回调函数的生命周期长于epoll_wait函数的调用。否则,在回调函数执行期间,可能会出现回调函数所引用的数据已经被销毁的情况,导致程序崩溃或产生其他不可预料的错误。
相关文章:
C++回调函数以及epoll中回调函数的使用
回调函数是一种常用的编程技术,它允许程序在运行时将一个函数作为参数传递给另一个函数,以实现更加灵活和可扩展的功能。在C中,回调函数通常被实现为函数指针或者函数对象。 函数指针是指向函数的指针变量,可以通过它来调用函数。…...
0基础学习软件测试有哪些建议
其实现在基础的资料和视频到处都是,就是看你有没有认真的去找学习资源了,去哪里学习都是要看你个人靠谱不靠谱,再好的教程和老师,你自己学习不进去也是白搭在正式选择之前,大可以在各种学习网站里面找找学习资源先自己…...
MySQL数据类型
文章目录一、数据类型分类二、数值类型1. tinyint 类型2. bit 类型3. int 类型4. float 类型5. decimal 类型三、字符串类型1. char 类型2. varchar 类型3. char 和 varchar 比较4.日期和时间类型5. enum 和 set一、数据类型分类 数据类型本质也是一种约束! 如果插入…...
【设计模式】从Mybatis源码中学习到的10种设计模式
文章目录 一、前言二、源码:学设计模式三、类型:创建型模式1. 工厂模式2. 单例模式3. 建造者模式 四、类型:结构型模式1. 适配器模式2. 代理模式3. 组合模式4. 装饰器模式 五、类型:行为型模式1. 模板模式2. 策略模式3. 迭代器模式…...
爬虫攻守道 - 猿人学第20题 - 殊途同归
写在开头 这题也是,自己搞顶多追踪到wasm代码,然后就走不下去了。找了2个参考方案,自己做的过程中还又遇到些新的问题,下面做个记录。解法1参考文章解法2参考文章 解法1:追根溯源 在 JS 代码中追踪到 Payload 赋值位…...
4.11日报
synchronized 和 ReentrantLock 区别是什么? synchronized 早期的实现比较低效,对比 ReentrantLock,大多数场景性能都相差较大,但是在 Java 6 中对 synchronized 进行了非常多的改进。 主要区别如下: ReentrantLock …...
【LeetCode每日一题: 1039. 多边形三角剖分的最低得分 | 暴力递归=>记忆化搜索=>动态规划 | 区间dp 】
🍎作者简介:硕风和炜,CSDN-Java领域新星创作者🏆,保研|国家奖学金|高中学习JAVA|大学完善JAVA开发技术栈|面试刷题|面经八股文|经验分享|好用的网站工具分享💎💎💎 🍎座右…...
Okio 网络提速
文章目录网络数据处理流程Page Cache传统 I/O 拷贝的性能问题零拷贝技术DMA 技术零拷贝技术分类mmapsendfilespliceDirect I/O零拷贝技术性能分析小结OkioOkio 的使用Okio 网络提速的原理Okio 总结总结网络数据处理流程 在讲 Okio 之前,为了能更好的了解 Okio 的优…...
自动驾驶企业面临哪些数据安全挑战?
近期,“特斯拉员工被曝私下分享用户隐私”不可避免地成了新闻热点,据说连马斯克也不能幸免。 据相关媒体报道,9名前特斯拉员工爆料在2019年至2022年期间,特斯拉员工通过内部消息系统私下分享了一些车主车载摄像头记录的隐私视频和…...
Doris(2):Doris编译部署
1 Doris编译 Apache Doris提供直接可以部署的版本压缩包:https://cloud.baidu.com/doc/PALO/s/Ikivhcwb5 也可以自行编译压缩包后使用(推荐) 1.1 使用 Docker 开发镜像编译(推荐) 这个是官方文档推荐的,…...
使用MyBatis实现简单查询
文章目录一,创建数据库与表(一)在Navicat里创建MySQL数据库testdb(二)创建用户表 - t_user(三)在用户表里插入3条记录二,案例演示MyBatis基本使用(一)创建Mav…...
C指针(*point)[4]和char *point[4]
char (*point)[4] // 数组指针。 a[3][4] // 先申明二维数组,用它来指向这个二维数组. char *point[4] // 指针数组。 a[4][5] // 一连串的指针. char (*point)[4] // 一个指针,指向有4个元素的数组;占内存大小为 4 个字节 ch…...
【Bard】谷歌的人工智能工具—Bard初体验
文章目录一、Bard介绍二、Bard体验1、加入Bard的候补名单2、登入Bard篇3、使用Bard篇(1)提供三种预选方式✨(2)创作生成各类文案(3)无生成图画能力(4)支持语音转文本输入✨ÿ…...
2022国赛30:windows脚本题解析
大赛试题内容: ( 九) ) 脚本 【任务描述】 为了减少重复性任务的工作量,节省人力和时间,请采用脚本,实现快速批量的操作。 1.在 windows4 上编写 C:\CreateFile.ps1 的 powershell 脚本,创建20 个文件 C:\test\File00.txt 至 C:\test\File19.txt,如果文件存在,则首先删除…...
Excel常用函数公式20例
目录 一、【IF函数条件判断】 二、【多条件判断】 三、【条件求和】 四、【多条件求和】 五、【条件计数】 六、【多条件计数】 七、【条件查找】 八、【多条件查找】 九、【计算文本算式】 十、【合并多个单元格内容】 十一、【合并带格式的单元格内容】 十二、…...
233:vue+openlayers绘制渐变填充色的圆形、多边形
第233个 点击查看专栏目录 本示例的目的是介绍如何在vue+openlayer中绘制带有渐变填充色的圆形、多边形。这里用canvas的方式去渲染,用到了DEVICE_PIXEL_RATIO,设备上的物理像素与设备无关像素 (dips) 之间的比率 (window.devicePixelRatio)。 直接复制下面的 vue+openlayer…...
Flink的窗口机制
窗口机制 tumble(滚动窗口) hop(滑动窗口) session(会话窗口) cumulate(渐进式窗口) Over(聚合窗口) 滚动窗口(tumble) 概念 滚…...
了解分布式Session
大家好,我这名CRUD工程师又来了,最近我的一个同事突然在看分布式Seesion的问题,然后我们两个也是互相讨论了一下,今天我就想着把分布式Session的知识点好好的梳理一下。 在很多系统中,用户的登录功能都是用Session去实…...
仿真创新大赛—国三省一 智能鱼缸(proteus)(stm32)
⏩ 大家好哇!我是小光,嵌入式爱好者,一个想要成为系统架构师的大三学生。 ⏩去年下半年参加了全国仿真创新大赛,也是取得了国赛三等奖,省赛一等奖的好成绩。 ⏩本篇文章对我们的参赛作品《智能鱼缸》做一个简介。 ⏩感…...
【ARMv8 编程】A64 数据处理指令——位域字节操作指令
有些指令将字节、半字或字扩展到寄存器大小,可以是 X 或 W。这些指令存在于有符号(SXTB、SXTH、SXTW)和无符号(UXTB、UXTH)变体中,并且是适当的位域操作指令。 这些指令的有符号和无符号变体都将字节、半字…...
python/java环境配置
环境变量放一起 python: 1.首先下载Python Python下载地址:Download Python | Python.org downloads ---windows -- 64 2.安装Python 下面两个,然后自定义,全选 可以把前4个选上 3.环境配置 1)搜高级系统设置 2…...
C++ 基础特性深度解析
目录 引言 一、命名空间(namespace) C 中的命名空间 与 C 语言的对比 二、缺省参数 C 中的缺省参数 与 C 语言的对比 三、引用(reference) C 中的引用 与 C 语言的对比 四、inline(内联函数…...
DBAPI如何优雅的获取单条数据
API如何优雅的获取单条数据 案例一 对于查询类API,查询的是单条数据,比如根据主键ID查询用户信息,sql如下: select id, name, age from user where id #{id}API默认返回的数据格式是多条的,如下: {&qu…...
k8s业务程序联调工具-KtConnect
概述 原理 工具作用是建立了一个从本地到集群的单向VPN,根据VPN原理,打通两个内网必然需要借助一个公共中继节点,ktconnect工具巧妙的利用k8s原生的portforward能力,简化了建立连接的过程,apiserver间接起到了中继节…...
QT: `long long` 类型转换为 `QString` 2025.6.5
在 Qt 中,将 long long 类型转换为 QString 可以通过以下两种常用方法实现: 方法 1:使用 QString::number() 直接调用 QString 的静态方法 number(),将数值转换为字符串: long long value 1234567890123456789LL; …...
Java面试专项一-准备篇
一、企业简历筛选规则 一般企业的简历筛选流程:首先由HR先筛选一部分简历后,在将简历给到对应的项目负责人后再进行下一步的操作。 HR如何筛选简历 例如:Boss直聘(招聘方平台) 直接按照条件进行筛选 例如:…...
什么是Ansible Jinja2
理解 Ansible Jinja2 模板 Ansible 是一款功能强大的开源自动化工具,可让您无缝地管理和配置系统。Ansible 的一大亮点是它使用 Jinja2 模板,允许您根据变量数据动态生成文件、配置设置和脚本。本文将向您介绍 Ansible 中的 Jinja2 模板,并通…...
AspectJ 在 Android 中的完整使用指南
一、环境配置(Gradle 7.0 适配) 1. 项目级 build.gradle // 注意:沪江插件已停更,推荐官方兼容方案 buildscript {dependencies {classpath org.aspectj:aspectjtools:1.9.9.1 // AspectJ 工具} } 2. 模块级 build.gradle plu…...
Java 二维码
Java 二维码 **技术:**谷歌 ZXing 实现 首先添加依赖 <!-- 二维码依赖 --><dependency><groupId>com.google.zxing</groupId><artifactId>core</artifactId><version>3.5.1</version></dependency><de…...
《C++ 模板》
目录 函数模板 类模板 非类型模板参数 模板特化 函数模板特化 类模板的特化 模板,就像一个模具,里面可以将不同类型的材料做成一个形状,其分为函数模板和类模板。 函数模板 函数模板可以简化函数重载的代码。格式:templa…...
