接上一篇,C++中,如何设计等价于Qt的信号与槽机制。

看下面例子:


class FileManager : public QObject {Q_OBJECTpublic:FileManager(QObject* parent = nullptr) : QObject(parent) {}void changeFileName(const QString& newName) {fileName = newName;emit fileNameChanged(fileName);}signals:void fileNameChanged(const QString& newName);private:QString fileName;
};

所有连接类FileManage中的信号,在changeFileName函数中被调用。例如:

int main(int argc, char* argv[])
{QApplication a(argc, argv);  //注意,这里是QApplicationFileManager fm;QObject::connect(&fm, &FileManager::fileNameChanged, [](const QString& newName) {std::cout << "函数1收到:文件名改变了。\n";});QObject::connect(&fm, &FileManager::fileNameChanged, [](const QString& newName) {std::cout << "函数2收到:文件名改变2。\n";});fm.changeFileName("abc");return a.exec();
}

输出:

下面我们也来设计相同功能的FileManager2:

class FileManager2 {
public:using fileNameChanged = std::function<void(const QString& newName)>;public:std::list< fileNameChanged> fileNameChanged_list;
public:FileManager2(QObject* parent = nullptr) {}void changeFileName(const QString& newName) {fileName = newName;for (fileNameChanged&  f: fileNameChanged_list) {if (f != 0)f(newName);}}void connect(fileNameChanged f) {fileNameChanged_list.push_back(f);}
private:QString fileName;
};int main(int argc, char* argv[])
{QApplication a(argc, argv);  //注意,这里是QApplicationFileManager2 fm;fm.connect([](const QString& newName) {std::cout << "函数1收到:文件名改变了。\n";});fm.connect([](const QString& newName) {std::cout << "函数2收到:文件名改变。\n";});fm.changeFileName("abc");return a.exec();
}

输出:

是不是一样,是不是很酷。:)

关键地方:

这里相当于Qt中的emit

这里添加一个函数指针,上篇说过:

这里可连接N个Lambda 表达式,与Qt一样:

连接函数:

最终也一样:

由于临时灵感来了,用了几分钟写的,难免有问题, 如果使用
std::list::remove 会编译不了,现在用新版方案替代,以后再完善:

template<class T>
class _callback {
public:friend bool  operator==(const _callback& l, const _callback& r) {return l.m_id == r.m_id;}_callback(const T& pf) {m_pf = pf;m_id = _DateTime::g_timeStamp();}public:__int64 m_id;T m_pf;
};class _FileManager {
public:using pf_fileNameChanged = std::function<void(const _string& oldPathName,const _string& newPathName)>;/// <summary>/// 更改文件名或路径并通知所有订阅者/// </summary>/// <param name="oldPathName"></param>/// <param name="newPathName"></param>/// 创建时间:2025-03-16    最后一次修改时间:2025-03-16void changeFileName(const _string& oldPathName, const _string& newPathName);/// <summary>/// 更改文件夹名或路径/// </summary>/// <param name="oldPathName"></param>/// <param name="newPathName"></param>/// 创建时间:2025-03-16    最后一次修改时间:2025-03-16void changeFolderName(const _string& oldPathName, const _string& newPathName);/// <summary>/// 删除文件/// </summary>/// <param name="fileName"></param>void deleteFile(const _string& fileName);/// <summary>/// 删除文件夹/// </summary>/// <param name="folderName"></param>void deleteFolder(const _string& folderName);// 订阅文件名更改事件void subscribe(const pf_fileNameChanged& callback) {std::lock_guard<std::mutex> lock(m_mutex); // 线程安全m_fileNameChanged.push_back(callback);}// 取消订阅文件名更改事件void unsubscribe(const pf_fileNameChanged& callback) {std::lock_guard<std::mutex> lock(m_mutex); // 线程安全m_fileNameChanged.remove(callback);}private:_string m_dirPathName; // 当前文件名std::list<_callback<pf_fileNameChanged>> m_fileNameChanged; // 订阅者列表mutable std::mutex m_mutex; // 用于线程安全
};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/34844.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

上传本地项目到GitHub

一、在GitHub上创建仓库 1.点击右上角头像–>点击Your repositories 2.点击New 3.创建仓库 网址复制一下&#xff0c;在后面git上传时会用到 二、打开Git Bash 1.cd 进入项目所在路径 2.输入git init 在当前项目的目录中生成本地的git管理&#xff08;当前目录下出现.…

基于Python的selenium入门超详细教程(第2章)--单元测试框架unittest

学习路线 自动化测试介绍及学习路线-CSDN博客 ​自动化测试之Web自动化&#xff08;基于pythonselenium&#xff09;-CSDN博客 基于Python的selenium入门超详细教程(第1章)--WebDriver API篇-CSDN博客 目录 前言&#xff1a; 一、单元测试 1. 单元测试的定义 2. 单元测…

HTML5 drag API实现列表拖拽排序

拖拽API&#xff08;Drag and Drop API&#xff09;是HTML5提供的一组功能&#xff0c;使得在网页上实现拖放操作变得更加简单和强大。这个API允许开发者为网页元素添加拖拽功能&#xff0c;用户可以通过鼠标将元素拖动并放置到指定的目标区域。 事件类型 dragstart&#xff1…

游戏引擎学习第163天

我们可以在资源处理器中使用库 因为我们的资源处理器并不是游戏的一部分&#xff0c;所以它可以使用库。我说过我不介意让它使用库&#xff0c;而我提到这个的原因是&#xff0c;今天我们确实有一个选择——可以使用库。 生成字体位图的两种方式&#xff1a;求助于 Windows 或…

Kafka可视化工具KafkaTool工具的使用

Kafka Tool工具 介绍 使用Kafka的小伙伴&#xff0c;有没有为无法直观地查看 Kafka 的 Topic 里的内容而发过愁呢&#xff1f;下面推荐给大家一款带有可视化页面的Kafka工具&#xff1a;Kafka Tool &#xff08;目前最新版本是 3.0.2&#xff09; 注意&#xff1a;以前叫Kafk…

在Spring Boot项目中接入DeepSeek深度求索,感觉笨笨的呢

文章目录 引言1. 什么是DeepSeek&#xff1f;2. 准备工作2.1 注册DeepSeek账号 3.实战演示3.1 application增加DS配置3.2 编写service3.3 编写controller3.4 编写前端界面chat.html3.5 测试 总结 引言 在当今快速发展的数据驱动时代&#xff0c;企业越来越重视数据的价值。为了…

【数据分析】读取文件

3. 读取指定列 针对只需要读取数据中的某一列或多列的情况&#xff0c;pd.read_csv()函数提供了一个参数&#xff1a;usecols&#xff0c;将包含对应的columns的列表传入该参数即可。 上面&#xff0c;我们学习了读取 "payment" 和 "items_count" 这…

Ubuntu 优化 Vim 指南

Vim 是一款功能强大的文本编辑器&#xff0c;通过合适的配置&#xff0c;可以变成一个接近 IDE 的高效开发工具。本指南提供 最精简、最实用 的 Vim 配置&#xff0c;满足 代码补全、语法高亮、代码格式化、目录管理等常用需求。 1. 必须安装的软件 首先&#xff0c;确保你的系…

信创环境下TOP5甘特图工具对比:从功能到适配性测评

在数字化转型的浪潮中&#xff0c;项目管理的高效与否直接决定了企业能否在激烈的市场竞争中脱颖而出。而甘特图作为项目管理中不可或缺的工具&#xff0c;其重要性不言而喻。尤其是在信创环境日益受到重视的当下&#xff0c;选择一款适配性强、功能完备的甘特图工具&#xff0…

MinIO的预签名直传机制

我们传统使用MinIo做OSS对象存储的应用方式往往都是在后端配置与MinIO的连接和文件上传下载的相关接口&#xff0c;然后我们在前端调用这些接口完成文件的上传下载机制&#xff0c;但是&#xff0c;当并发量过大&#xff0c;频繁访问会对后端的并发往往会对服务器造成极大的压力…

【NLP 38、实践 ⑩ NER 命名实体识别任务 Bert 实现】

去做具体的事&#xff0c;然后稳稳托举自己 —— 25.3.17 数据文件&#xff1a; 通过网盘分享的文件&#xff1a;Ner命名实体识别任务 链接: https://pan.baidu.com/s/1fUiin2um4PCS5i91V9dJFA?pwdyc6u 提取码: yc6u --来自百度网盘超级会员v3的分享 一、配置文件 config.py …

Windows下安装MongoDB 8

在Windows下安装MongoDB&#xff0c;首先需要确定自己的Windows系统版本以及MongoDB社区版所能支持的系统版本。这里使用的是Windows 10操作系统和MongoDB 8.0.4版本。由于MongoDB 6版本之后&#xff0c;不再默认安装Mongo Shell&#xff0c;所以本节分为两部分&#xff1a;安装…

【Node.js入门笔记4---fs 目录操作】

Node.js入门笔记4 Node.js---fs 目录操作一、目录操作1.fs.mkdir()&#xff1a;创建目录。异步&#xff0c;非阻塞。创建单个目录创建多个目录创建目前之前需要确认是否存在&#xff1a; 2. fs.mkdirSync()&#xff1a;用于创建一个新的目录。异步&#xff0c;非阻塞。3.fs.rmd…

DeepSeek-R1思路训练多模态大模型-Vision-R1开源及实现方法思路

刚开始琢磨使用DeepSeek-R1风格训练多模态R1模型&#xff0c;就看到这个工作&#xff0c;本文一起看看&#xff0c;供参考。 先提出问题&#xff0c;仅靠 RL 是否足以激励 MLLM 的推理能力&#xff1f; 结论&#xff1a;不能&#xff0c;因为如果 RL 能有效激励推理能力&#…

Python学习第十八天

Django模型 定义&#xff1a;模型是 Django 中用于定义数据库结构的 Python 类。每个模型类对应数据库中的一张表&#xff0c;类的属性对应表的字段。 作用&#xff1a;通过模型&#xff0c;Django 可以将 Python 代码与数据库表结构关联起来&#xff0c;开发者无需直接编写 S…

总结 HTTP 协议的基本格式, 相关知识以及抓包工具fiddler的使用

目录 1 HTTP是什么 2 HTTP协议格式 3 HTTP请求(Request) 3.1 认识URL 3.2 方法 3.3 认识请求"报头"(header) 3.3.1 Host 3.3.2 Content-Length 3.3.3 Content-Type 3.3.4 User-Agent (简称UA) 3.3.5 Referer 3.3.6 Cookie和Session 4 HTTP响应详解 4.…

【sql靶场】第15、16关-post提交盲注保姆级教程

目录 【sql靶场】第15、16关-post提交盲注保姆级教程 1.知识回顾 ‌GET请求‌ ‌POST请求‌ or与and 2.第十五关 1.布尔盲注的手动注入 1.判断 2.数据库名长度 3.数据库名字符 4.表名数 5.表名长度 6.表名符 7.字段数 8.字段长度 9.字段符 2.布尔盲注的脚本注入…

【C++】 —— 笔试刷题day_6

刷题day_6&#xff0c;继续加油哇&#xff01; 今天这三道题全是高精度算法 一、大数加法 题目链接&#xff1a;大数加法 题目解析与解题思路 OK&#xff0c;这道题题目描述很简单&#xff0c;就是给我们两个字符串形式的数字&#xff0c;让我们计算这两个数字的和 看题目我…

redis终章

1. 缓存(cache) Redis最主要的用途&#xff0c;三个方面1.存储数据&#xff08;内存数据库&#xff09;&#xff1b;2.缓存[redis最常用的场景]&#xff1b;3.消息队列。 缓存(cache)是计算机中的⼀个经典的概念.核⼼思路就是把⼀些常⽤的数据放到触⼿可及(访问速度更快)的地⽅…

Matlab 多输入系统极点配置

1、内容简介 略 Matlab 172-多输入系统极点配置 可以交流、咨询、答疑 2、内容说明 略 3、仿真分析 略 clc close all clear A [-6.5727 1.1902 0 -53.4085;1.1902 -6.5727 0 -53.4085;0.5294 0.5294 0 17.7502;0 0 1 0]; B [1.3797 -0.2498;-0.2498 1.3797;-0.1111 -0.1…