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

news2025/4/16 19:17:28

看下面例子:


class FileManager : public QObject {
    Q_OBJECT

public:
    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);  //注意,这里是QApplication
 
	FileManager 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);  //注意,这里是QApplication
 
	FileManager2 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-16
    void changeFileName(const _string& oldPathName, const _string& newPathName);


    /// <summary>
    /// 更改文件夹名或路径
    /// </summary>
    /// <param name="oldPathName"></param>
    /// <param name="newPathName"></param>
    /// 创建时间:2025-03-16    最后一次修改时间:2025-03-16
    void 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.coloradmin.cn/o/2316748.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

安装baselines出现的环境配置问题

该错误通常是由于环境配置问题、依赖包缺失、权限不足等原因导致 1. 更新相关工具 pip install --upgrade pip setuptools 2. 检查并安装依赖 conda install setuptools pip wheel 出现新问题&#xff1a; 3.尝试使用 Conda 安装 conda install mpi4py 再尝试安装 baseli…

perl的package中“Subroutine new redefined”问题

我在一个脚本run_PMseq.V8.pl调用了一些.pm文件 $perl -c run_PMseq.V8.pl Subroutine new redefined at /mnt/lustre/user/wubin/01.Program/Scripts/01.script/GeneLab/PMSeq/package_V3/Add_mismatch.pm line 25. Subroutine generate_shell redefined at /mnt/lustre/use…

英语学习(GitHub学到的分享)

【英语语法&#xff1a;https://github.com/hzpt-inet-club/english-note】 【离谱的英语学习指南&#xff1a;https://github.com/byoungd/English-level-up-tips/tree/master】 【很喜欢文中的一句话&#xff1a;如果我轻轻松松的学习&#xff0c;生活的幸福指数会提高很多…

【eNSP实战】三层交换机使用ACL实现网络安全

拓图 要求&#xff1a; vlan1可以访问Internetvlan2和vlan3不能访问Internet和vlan1vlan2和vlan3之间可以互相访问PC配置如图所示&#xff0c;这里不展示 LSW1接口vlan配置 vlan batch 10 20 30 # interface Vlanif1ip address 192.168.40.2 255.255.255.0 # interface Vla…

Javascript BOM,DOM 知识简介

JSON 一种数据交换格式,作为数据载体,传输数据, Json比xml 更简单,可读性更高.js的对象和Json可以相互转换. //json定义格式: var varName{"key1":value1,"key2":value2};value的数据类型为数字,字符串(在双引号中),布尔值,数组(在方括号中),对象(在花括…

拆解 “ES 已死“ 伪命题:Agentic RAG 时代搜索引擎的终极形态

作者&#xff1a;来自 Elastic 李捷 xxx&#xff1a;“ES已死&#xff0c;#%#……” 我&#xff1a;&#xff1f;&#xff1f;&#xff1f; 最近&#xff0c;某厂商发了一堆公关文章&#xff0c;翻来覆去地炒作 “ES 已死”&#xff0c;“放弃 ES”。这哪是什么正经的技术文章&…

.net 6程序在IIS中部署后点击IIS设置报错“执行此操作时出错”

.net 6写的程序&#xff0c;需要在Windows服务器的IIS中部署&#xff0c;由于是刚装的系统&#xff0c;先安装.net 6运行时&#xff0c;装了才发现没有IIS&#xff0c;于是又通过“添加角色和功能”添加与IIS相关的功能。安装完毕后&#xff0c;在IIS中添加网站&#xff0c;并将…

《从零手写Linux Shell:详解进程控制、环境变量与内建命令实现 --- 持续更新》

承接上文Linux 进程的创建、终止、等待与程序替换保姆级讲解-CSDN博客&#xff0c;涉及所用到的代码&#xff0c;本文所绑定的资源就是上篇文章的主要代码。 完整代码在文章末尾 目录 1.实现编写代码输出一个命令行 a.如何获取自己的用户名&#xff0c;主机名&#xff0c;路径…

k8s环境部署

四台机器 分别是 k8s-master&#xff1a;172.25.254.100 k8s-node1&#xff1a;172.25.254.10 k8s-node2&#xff1a;172.25.254.20 docker-harbor&#xff1a;172.25.254.200 reg.timinglee.org 四台机器分别配置好网络和软件仓库 做好地址解析 scp -r /etc/hosts/ root17…

CentOS 系统安装 docker 以及常用插件

博主用的的是WindTerm软件链接的服务器&#xff0c;因为好用 1.链接上服务器登入后&#xff0c;在/root/目录下 2.执行以下命令安装docker sudo yum install -y yum-utilssudo yum-config-manager \--add-repo \https://download.docker.com/linux/centos/docker-ce.reposudo…

谷歌云服务器:服务器怎么安装???

谷歌云服务器&#xff1a;服务器怎么安装&#xff1f;&#xff1f;&#xff1f; 以下是详细分步指南&#xff0c;帮助你在 Google Cloud Platform (GCP) 上快速创建并配置云服务器&#xff08;Compute Engine 实例&#xff09;&#xff0c;并安装所需环境&#xff1a; 一、准备…

Redis--Zset类型

目录 一、引言 二、介绍 三、命令 1.zadd 2.zrange&#xff0c;zrevrange&#xff0c;zrangebyscore 3.zcard&#xff0c;zcount 4.zpopmax&#xff0c;bzpopmax&#xff0c;zpopmin&#xff0c;bzpopmin 5.zrank,zrevrank,zscore 6.zrem&#xff0c;zremrangebyrank&a…

《阿里云Data+AI:开启数据智能新时代》电子书上线啦!

本书整理了阿里云在DataAI领域的最新实践案例与深度洞察&#xff0c;涵盖电商、游戏、营销、数字内容等多个行业的成功经验&#xff0c;以及技术专家对数据库与AI融合趋势的专业解读。 通过理论与实践的结合&#xff0c;我们将共同探索DataAI如何成为企业智能化转型的核心驱动…

Golang编译器DIY,手搓 if err != nil { return err } 语法糖

前序 在go的社区里&#xff0c;下面这三行代码是被吐槽的最多的 if err ! nil {return err }从代码之整洁美观的角度看&#xff0c;这样的写法也是让人不舒服的。尤其是 当有很多错误需要处理的时候&#xff0c;就会发现通篇都是这三行。 所以想着看看修改一下编译器&#xf…

图解多头注意力机制:维度变化一镜到底

目录 一、多头注意力机制概述二、代码实现1. pyTorch 实现2. tensorFlow实现 三、维度变化全流程详解1. 参数设定2. 维度变化流程图3. 关键步骤维度变化 四、关键实现细节解析1. 多头拆分与合并2. 注意力分数计算3. 掩码处理技巧 五、完整运行示例六、总结与常见问题1. 核心优势…

[ISP] 人眼中的颜色

相机是如何记录颜色的&#xff0c;又是如何被显示器还原的&#xff1f; 相机通过记录RGB数值然后显示器显示RGB数值来实现颜色的记录和呈现。道理是这么个道理&#xff0c;但实际上各厂家生产的相机对光的响应各不相同&#xff0c;并且不同厂家显示器对三原色的显示也天差地别&…

解锁MySQL 8.0.41源码调试:Mac 11.6+CLion 2024.3.4实战指南

文章目录 解锁MySQL 8.0.41源码调试&#xff1a;Mac 11.6CLion 2024.3.4实战指南前期准备环境搭建详细步骤安装 CLion安装 CMake 3.30.5准备 MySQL 8.0.41 源码配置 CMake 选项构建 MySQL 项目 调试环境配置与验证配置 LLDB 调试器启动调试验证调试环境 总结与拓展 解锁MySQL 8…

关于xcode Project navigator/项目导航栏的一些说明

本文基于 xcode12.4 版本做说明 首先要明确一点&#xff0c;导航栏这里展示的并不是当前工程在电脑硬盘中的文件结构&#xff0c;它展示的是xxxxxx.xcodeproj/project.pbxproj文件(后文简.pbxproj文件)中的内容。我们在导航栏中的操作就是修改该文件&#xff0c;有些操作会修…

深度解析扣减系统设计:从架构到实践

背景 在当今数字化业务蓬勃发展的时代&#xff0c;扣减系统在众多业务场景中扮演着关键角色。无论是电商平台的库存扣减&#xff0c;还是金融领域的资金扣减、积分系统的积分扣减&#xff0c;一个高效、可靠且数据一致的扣减系统都是业务稳健运行的基石。本文将深入探讨扣减系…

视觉定位项目中可以任意修改拍照点位吗?

修改拍照点位不是那么简单 1. 背景2. 修改拍照点位意味着什么&#xff1f;3. 如何解决这个问题&#xff1f; 1. 背景 在视觉定位的项目中&#xff0c;会遇到这么一种情况&#xff1a;完成三步&#xff08;9点标定&#xff0c;旋转中心标定&#xff0c;示教基准&#xff09;之…