C++中如何实现简单的观察者模式_C++解耦组件间通信方法【设计】-C++

用std::function+std::vector可轻量实现观察者模式,核心是存储回调并遍历通知;需规避悬空指针、迭代器失效及自我注销问题,推荐结合weak_ptr/shared_ptr管理生命周期,比虚函数继承更灵活高效。

用 std::function + std::vector 实现轻量观察者注册表

不需要引入第三方库或复杂基类,C++11 起就能靠标准库搭出可用的观察者模式。核心是把回调抽象为 std::function(或带参数的变体),用 std::vector 存储,注册即 push_back,通知即遍历调用。

常见错误是直接存裸函数指针或 lambda 捕获局部变量,导致调用时悬空。必须确保回调对象生命周期长于观察者容器,或用 std::shared_ptr 管理。

  • 推荐签名: using Callback = std::function;,Event 是自定义结构体,比 void* 安全、比模板泛型更易维护
  • 注册时检查重复:可加 std::weak_ptr 配合 std::shared_ptr 实现自动去重与自动注销
  • 通知时避免迭代器失效:若回调内可能调用 unregister(),需先拷贝回调列表再遍历

如何安全处理观察者在回调中自我注销

这是最常踩的坑:遍历时删除容器元素,引发迭代器失效和未定义行为。不能边 for-range 边 erase。

正确做法是分离“通知”和“清理”。先收集待移除项,或改用索引遍历并倒序删,但更稳妥的是两阶段策略:

立即学习“C++免费学习笔记(深入)”;

  • 第一阶段:遍历原始 std::vector>,调用 lock() 获取有效回调,存入临时 std::vector>
  • 第二阶段:遍历临时列表执行调用;结束后再扫描原容器,erase 已过期的 weak_ptr
  • 如果不用智能指针,就要求调用方显式调用 unregister(),并在容器内部用 std::list 替代 std::vector,支持 O(1) 删除

为什么不用虚函数+继承实现?

纯虚基类(如 class Observer { virtual void onEvent(const Event&) = 0; };)看似经典,但在现代 C++ 中往往过度设计:

  • 每个具体观察者都要继承、实现虚函数,增加编译依赖和头文件耦合
  • 多态调用有虚表开销,虽小但对高频事件(如游戏帧更新)可测出差异
  • 无法直接绑定成员函数而不传对象指针,需额外包装(std::bind 或 lambda),反而不如 std::function 直观
  • 不支持无状态函数、静态函数、函数对象等灵活来源

除非你已有严格接口契约、需要运行时动态切换观察者类型,否则没必要上继承体系。

Qt 的 QObject::connect() 和标准库方案本质区别在哪

Qt 版本不是“更高级”,而是为特定场景深度优化:信号与槽自动管理对象生命周期(父对象析构时自动断连)、线程安全(跨线程队列投递)、元对象系统支持字符串名连接。这些都以宏、moc 编译器和运行时开销为代价。

标准库方案没这些——它也不该有。如果你的模块不涉及 GUI、不跨线程通信、不需要运行时反射,硬套 Qt 机制反而让逻辑变得隐晦且难测试。

真正要注意的是:Qt 的连接默认是 Qt::AutoConnection,跨线程时会排队,而手写方案默认是同步调用,想异步必须自己扔进 std::thread 或 std::async,这点容易忽略。

夏夕资源网专注于CMS网站模板,主流语言整站网站源码下载,网站建设相关教程分享,好用的软件素材整合下载,提供一站式便捷自助服务。
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需!
7. 如遇到加密压缩包,默认解压密码为"zy.lucklyus.top",如遇到无法解压的请联系管理员!
夏夕资源网-网站模板_免费源码_资源素材 » C++中如何实现简单的观察者模式_C++解耦组件间通信方法【设计】-C++
在线时间:12:00 - 22:00
关注微信公众号:微信公众号
站长邮箱:[email protected]
  • 运营天数: 1391+
  • 资源总数: 47989+
  • 用户总数: 1+
  • 今日更新: 0+
  • 访问次数: 3994697+
  • 本周更新: 0+
  • 最后更新: 2026-03-16

本站指数

×
  • 运营天数: 1391+
  • 资源总数: 47989+
  • 用户总数: 1+
  • 今日更新: 0+
  • 访问次数: 3994697+
  • 本周更新: 0+
  • 最后更新: 2026-03-16