答案:通过std::function和可变模板参数实现支持多类型槽函数的信号机制,具备连接管理与解耦特性。

在C++中实现一个简单的信号与槽机制,核心目标是解耦对象之间的通信。Qt框架中的信号槽非常经典,但不依赖Qt时,我们可以通过现代C++(如C++11及以上)的特性,比如std::function、可变模板参数和std::shared_ptr来实现一个轻量级版本。
信号(Signal)是一个事件发生的通知者,槽(Slot)是响应这个事件的函数。我们需要做到:
这里采用基于std::function存储回调,并用连接ID管理订阅关系。
定义一个模板类Signal,支持任意参数的函数签名:
#include <vector>
#include <functional>
#include <algorithm>
template <typename... Args>
class Signal {
private:
using SlotType = std::function<void(Args...)>;
std::vector<SlotType> slots_;
int next_id_ = 0;
std::vector<int> free_ids_;
public:
// 连接一个槽函数,返回连接ID
int connect(SlotType slot) {
int id;
if (free_ids_.empty()) {
id = next_id_++;
slots_.push_back(slot);
} else {
id = free_ids_.back();
free_ids_.pop_back();
slots_[id] = slot;
}
return id;
}
// 断开连接
void disconnect(int id) {
if (id >= 0 && id < (int)slots_.size() && slots_[id]) {
slots_[id] = nullptr;
free_ids_.push_back(id);
}
}
// 触发信号,调用所有有效槽
void emit(Args... args) {
for (const auto& slot : slots_) {
if (slot) {
slot(args...);
}
}
}
};
下面演示如何连接普通函数、lambda和成员函数:
RhaPHP微信公众号管理系统
RhaPHP 是一款免费开源的微信公众号管理营销系统!也是一款微信公众号开发框架。简洁,灵活,快速易开发,应用模块化,支持移动端管理微信公众号。基于 THINKPHP5,简单的代码即可实现微信公众号通信与接口实现。不需要花大量时间研究系统即可快速开发微信应用,rhaphp在微信开发有着灵活机制,支持移动管理微信公众号。系统运行环境 PHP+MYSQL。
2
查看详情
#include <iostream>
struct Receiver {
void onEvent(int value) {
std::cout << "Received: " << value << "\n";
}
};
void globalCallback(int value) {
std::cout << "Global handler: " << value << "\n";
}
int main() {
Signal<int> sig;
Receiver receiver;
// 连接全局函数
int conn1 = sig.connect(globalCallback);
// 连接lambda
int conn2 = sig.connect([](int v) {
std::cout << "Lambda received: " << v << "\n";
});
// 连接成员函数(注意捕获receiver实例)
int conn3 = sig.connect([&receiver](int v) {
receiver.onEvent(v);
});
// 发送信号
sig.emit(42);
// 断开某个连接
sig.disconnect(conn2);
std::cout << "After disconnecting lambda:\n";
sig.emit(100);
return 0;
}
输出结果:
Global handler: 42 Lambda received: 42 Received: 42 After disconnecting lambda: Global handler: 100 Received: 100
当前实现简单实用,但可用于生产环境前建议增强以下几点:
slots_的访问应加锁(如std::mutex)std::weak_ptr检测生命周期Connection类,支持RAII自动断开基本上就这些。这个轻量级信号槽机制适合嵌入小型项目或学习事件驱动编程模型,不复杂但足够灵活。
以上就是c++++怎么实现一个简单的信号槽机制_c++信号与槽机制的实现与应用的详细内容,更多请关注其它相关文章!
相关文章:
J*aScript DOM操作:高效清空列表元素的策略与实践
构建轻量级网站内部消息系统:Formspree 集成指南
J*aScript中在Map循环中检测并处理空数组元素
必由学官方登录入口 必由学教师学生账号快速访问
Composer的 archive 命令怎么用_快速打包你的PHP项目及其Composer依赖
LINUX下如何进行磁盘分区_fdisk与parted工具在LINUX中的使用对比
PHP文件上传至S3:策略、考量与避免本地存储的挑战
Python大型XML文件高效流式解析教程
天眼查企业查询官网入口 天眼查官方网页版查询
汽水音乐在线解析 汽水音乐在线解析入口
sublime怎么格式化代码_sublime代码美化与一键排版插件配置
Golang如何使用net/url解析URL_Golang URL解析与处理方法
Node.js CSV 数据处理:基于字段空值条件过滤整条记录的策略
漫蛙manwa官网登录界面_漫蛙漫画网页版主站入口
Go语言中高效处理x-www-form-urlencoded表单数据
在J*a中如何使用BigDecimal进行高精度计算_BigDecimal类应用指南
腾讯视频怎么举报不良内容_腾讯视频内容举报流程与违规信息处理方法
Tailwind CSS line-clamp 布局问题解析与修复指南
在J*a中如何使用ForkJoinPool进行分治任务并行处理_ForkJoinPool分治并行技巧说明
Odoo 16:在表单视图中基于当前记录动态修改Tree视图属性
j*a toString()的覆盖
Yandex搜索引擎官网入口_俄罗斯Yandex免登录一键直达
漫蛙2正版漫画站 漫蛙2网页版快速访问入口
PHP教程:高效从URL路径中提取倒数第二个片段
PHP面向对象编程中避免重复创建PDO数据库连接的最佳实践
b站如何看历史记录_b站观看历史找回方法
铁路12306卧铺选择攻略 铁路12306下铺座位预定技巧
J*aScript类型检查_j*ascript代码规范
移动端XML文件怎么转换成Excel 手机和平板上的解决方案
Typer应用中动态命令行参数的解析与处理
HuggingFaceEmbeddings中向量嵌入维度调整的限制与理解
优化Log4j2控制台输出性能:解决异步日志瓶颈
《主播少女的秘密账号迷宫》首支宣传片
sublime怎么预览Markdown渲染效果_Markdown Preview插件 for sublime教程
c++如何实现单例设计模式_c++线程安全的单例模式写法
Win11怎么开启高性能模式_Windows 11电源计划优化设置
Python复杂任务中断策略:通过回调函数实现优雅停止
德邦快递查询平台 德邦快递物流信息查询入口
C++如何生成随机数_C++ random库使用方法与范围设置
Go语言:非阻塞式判断标准输入(os.Stdin)是否有数据
黑鲨3Pro怎样在相册开漫画风滤镜_iPhone黑鲨3Pro相册开漫画风滤镜【趣味滤镜】
在Go Martini框架中高效服务动态生成图像的实践指南
excel怎么制作工资条 excel快速生成工资条的方法
解决Django多数据库/多Schema环境下外键迁移问题
Excel如何用迷你图显趋势_Excel用迷你图显趋势【趋势小图】
Windows10怎么开启存储感知 Windows10系统设置自动清理临时文件释放C盘空间【教程】
哔哩哔哩忘记密码了怎么找回_哔哩哔哩密码找回方法
Basecamp怎样用留言钉固定重点_Basecamp用留言钉固定重点【重点标记】
Win10如何清理注册表垃圾 Win10手动清理无效注册表【技巧】
ExcelARRAYTOTEXT函数怎么自定义分隔符输出数组文本_ARRAYTOTEXT实现动态生成SQL语句