您的位置:首页 > 财经 > 金融 > 技术转让网_h5开发小程序_seo北京优化_滨州网站建设

技术转让网_h5开发小程序_seo北京优化_滨州网站建设

2025/4/28 15:04:58 来源:https://blog.csdn.net/Interview_TC/article/details/147159558  浏览:    关键词:技术转让网_h5开发小程序_seo北京优化_滨州网站建设
技术转让网_h5开发小程序_seo北京优化_滨州网站建设

📘 本篇围绕 Qt 编程中最经典的设计之一——Signal/Slot(信号-槽)机制进行完整复现与讲解。从原理推导到实战构建,我们将结合 Day 10~11 的回调与观察者经验,逐步实现一个类型安全、生命周期安全、支持弱引用与自动解绑的轻量信号-槽系统,打通事件驱动设计能力。


🔁 Day 11 回顾:观察者模式构建要点

模块内容总结
发布者-订阅者模型通过模板与 function 实现注册/通知体系
weak_ptr 防悬空使用智能指针确保观察者自动失效,不崩溃
事件 ID 注册机制通过 Token 管理连接与解绑
模板化封装支持任意参数传递、任意观察者结构

📌 本篇将在此基础上,引入 Slot(槽函数)+ Signal(信号发出者)模型,实现更自然、简洁的连接调用体验。


🎯 今日目标:构建轻量级 Signal/Slot 通信系统

组件功能说明
Signal<T…>提供 connect/disconnect/emit 接口
Slot / 回调支持任意类型可调用对象,包括成员函数与 Lambda
生命周期安全使用 weak_ptr 避免调用已销毁对象
高级支持一次性连接、临时解绑、参数任意、嵌套安全调用

在这里插入图片描述

✅ 一、设计动机:Signal/Slot 比观察者更优在哪里?

🔍 特点对比:

功能维度观察者模式Signal/Slot
注册方式通常使用注册函数(如 addObserver)使用 connect 连接 signal 与 slot
调用触发使用 notifyAll()signal.emit(…)
参数泛型支持需手动泛型模板内封装参数类型
支持成员方法需配合 bind/std::function可直接连接成员函数 + this
生命周期安全weak_ptr + lock内部管理 weak_ptr,自动判断失效

📌 Signal/Slot 更适合构建“模块间解耦事件响应机制”,特别是 UI 与业务层之间。


✅ 二、基本骨架设计:Signal 模板类

#include <functional>
#include <unordered_map>
#include <memory>
#include <iostream>template<typename... Args>
class Signal {
public:using Slot = std::function<void(Args...)>;using Token = size_t;Token connect(Slot slot) {slots[++counter] = slot;return counter;}void disconnect(Token token) {slots.erase(token);}void emit(Args... args) {for (auto& [_, fn] : slots) {fn(args...);}}private:std::unordered_map<Token, Slot> slots;Token counter = 0;
};

📌 接口说明:

  • connect(fn):注册一个槽函数,返回唯一连接标识
  • disconnect(id):根据 ID 解绑指定回调
  • emit(...):发送信号,自动调用所有注册函数

✅ 三、支持成员函数 + 弱引用绑定

🔸 辅助工具:bindWeakMember

template<typename T, typename... Args>
std::function<void(Args...)> bindWeakMember(std::weak_ptr<T> wp, void (T::*method)(Args...)) {return [wp, method](Args... args) {if (auto sp = wp.lock()) {(sp.get()->*method)(args...);}};
}

📌 用法:防止调用已销毁对象成员,自动跳过

🔸 示例结构:

struct Receiver : public std::enable_shared_from_this<Receiver> {void handle(int val) {std::cout << "📥 接收值:" << val << "\n";}
};Signal<int> sig;{auto r = std::make_shared<Receiver>();sig.connect(bindWeakMember(r, &Receiver::handle));sig.emit(100); // 正常输出
}sig.emit(200); // 已销毁,自动跳过

✅ 四、拓展功能:一次性连接 / 自动解绑

🔸 一次性连接 once

template<typename... Args>
class SignalOnce : public Signal<Args...> {
public:typename Signal<Args...>::Token connectOnce(typename Signal<Args...>::Slot slot) {auto id = this->connect([this, slot, id = this->nextId()] (Args... args) mutable {slot(args...);this->disconnect(id);});return id;}private:typename Signal<Args...>::Token nextId() { return ++this->counter; }
};

📌 适用场景:仅需一次响应的事件(如初始化完毕、一次确认)


✅ 五、完整应用案例:业务模块通信

📦 定义模块

class LoginManager {
public:Signal<std::string> onLoginSuccess;void login() {std::cout << "🔐 登录中...\n";onLoginSuccess.emit("user123");}
};class ChatPanel : public std::enable_shared_from_this<ChatPanel> {
public:void onUserReady(const std::string& uid) {std::cout << "💬 欢迎用户:" << uid << " 进入聊天室\n";}
};

🤝 模块连接:

auto chat = std::make_shared<ChatPanel>();
LoginManager login;
login.onLoginSuccess.connect(bindWeakMember(chat, &ChatPanel::onUserReady));login.login(); // 输出登录 & 聊天面板响应

✅ 六、经验总结

设计目标实现方式
支持多回调使用 map 储存 slots
生命周期安全使用 weak_ptr + lock
支持任意参数函数使用模板参数展开
支持解绑/一次性调用提供 token + connectOnce 接口
支持成员方法绑定使用 bindWeakMember 工具函数

📌 Signal/Slot 是观察者模式的模板化封装 + 生命周期控制的优雅实现方式。


📘 实战反思与扩展建议

  • 在 UI、游戏、客户端业务中非常适用
  • 可拓展支持事件分组、跨线程调用、异步触发
  • 可结合线程池、事件队列构建完整事件调度系统

🔭 Day 13 预告:协程 + 异步模型整合信号响应

下一篇将结合:

  • std::future / std::promise + Signal
  • 信号触发后自动 resume 协程流程
  • 构建“异步事件驱动业务模块”的基本框架

📌 如果你希望结合 GUI、游戏引擎、任务调度等真实项目场景,我可优先提供方向图与代码结构 💡

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com