讲师中心 微信公众号
AI工具推荐 视频效率加速

c++怎么实现简单的观察者模式_c++事件回调机制【实战】

冬芳同学_8630

冬芳同学_8630

发布时间:2026-03-13 20:12:31

|

1019人浏览过

|

来源于php中文网

原创

可用std::function+std::vector实现轻量观察者:用vector存储回调,避免裸指针生命周期问题;需确保捕获对象生命周期≥subject,推荐shared_ptr或weak_ptr管理;安全删除用remove_if+erase或两阶段标记;比signals2等库更简洁高效。

c++怎么实现简单的观察者模式_c++事件回调机制【实战】

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

不用模板元编程或信号槽库,也能在 C++11 起写出干净、可读、够用的观察者。核心是把回调抽象成 std::function<void></void> 或带参变体,用 std::vector 存储,避免裸指针生命周期问题。

常见错误现象:std::function 捕获了局部对象(比如 lambda 里用了栈上变量),注册后回调时访问野内存;或者用 raw pointer 存 observer,被析构后没清理,触发 std::bad_function_call。

  • 注册回调必须确保捕获的对象生命周期 ≥ subject 生命周期,推荐用 shared_ptr 管理 observer,或只捕获 this(且保证 observer 不先于 subject 销毁)
  • 参数类型要对齐:subject 通知时传 int,observer 注册的 std::function<void></void> 才能接住;不匹配会编译失败
  • 避免在回调中调用 unregister() —— 遍历 vector 时修改它,容易跳过下一个元素或迭代器失效

如何安全地移除正在执行的观察者

遍历时删元素是经典坑。不能边 for (auto it = v.begin(); it != v.end(); ++it) 边 v.erase(it),迭代器立刻失效。

使用场景:某个 UI 控件销毁前主动解绑,或网络模块断连后清理回调。

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

C++ Code Review Master
C++ Code Review Master

组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。

下载
  • 推荐“两阶段删除”:先标记待删项(比如用 std::optional<:function>></:function> 或布尔 flag),循环结束后统一擦除
  • 更简单做法:用 std::remove_if + erase 惯用法,前提是判断逻辑不依赖外部状态变更
  • 如果必须实时解绑,改用 std::list + erase 返回下一节点迭代器,但 list 缓存不友好,小规模观察者用 vector 更快

std::weak_ptr 解决 observer 生命周期失控

当 observer 是某个类实例,而 subject 是全局/单例,容易出现 subject 活着但 observer 已析构,回调时 crash。

性能影响:每次通知前需调用 lock(),有原子操作开销,但比崩溃强得多。

  • subject 存的是 std::vector<:weak_ptr>></:weak_ptr>,不是 shared_ptr 或 raw pointer
  • 通知时对每个 weak_ptr 调用 lock(),得到 shared_ptr 再判空,非空才调用其方法
  • 不要在 observer 析构函数里反向调用 subject 的 unregister() —— 此时 subject 可能已在析构,导致未定义行为

为什么别急着上 boost::signals2 或 Qt 的 QObject::connect

这些库功能全,但引入依赖、编译慢、调试难,尤其嵌入式或命令行工具里,一个 std::vector<:function></:function> 加几十行代码就能覆盖 90% 场景。

兼容性影响:Qt 的信号槽要求 moc,跨线程需 QueuedConnection,隐式拷贝参数;boost::signals2 在 C++17 下和 std::any / std::variant 协作不够自然。

  • 纯异步通知?自己加个 std::queue + std::mutex 就行,比学 signals2 的线程模型快
  • 需要自动断连?weak_ptr 方案已解决,且无反射开销
  • 真要多线程安全发布?别锁整个 notify,用 std::atomic<bool></bool> 标记是否正在通知,让 unregister 等待,比粒度更细的锁更容易验证

真正复杂的是跨模块所有权和线程边界,不是“怎么注册回调”——把 weak_ptr 和生命周期语义理清楚,比套任何框架都管用。

相关文章

c++速学教程(入门到精通)
c++速学教程(入门到精通)

c++怎么学习?c++怎么入门?c++在哪学?c++怎么学才快?不用担心,这里为大家提供了c++速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

c++

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热门AI工具

更多
PixTV
PixTV Hot

PixTV是一款面向AIGC内容创作的AI视频生成工具。

WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

SkildArt
SkildArt Hot

SkildArt是一款AI文本写作工具,一站式 AI 视觉创作平台。

立刻MV
立刻MV Hot

立刻MV是一款AI文本写作工具,AI 音乐视频(MV)创作工具。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

PixPix
PixPix Hot

PixPix是一款面向电商视觉生产的AI商品图生成工具。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

LibLibAI
LibLibAI Hot

一款AI视频创作工具,主要用于国内领先的AI创意平台,以海量模型、低门槛操作与“创作-分享-商业化”生态,让小白与专业创作者都能高效实现图文乃至视频创意表达,适合需要提升相关任务效率的用户。

二狗PPT
二狗PPT Hot

一款AI演示文稿工具,主要用于专为中式职场打造的AI PPT生成工具,适合需要提升相关任务效率的用户。

相关专题

更多
C++ Qt图形开发
C++ Qt图形开发

本专题专注于 C++ Qt框架在图形界面开发中的应用,系统讲解窗口设计、信号与槽机制、界面布局、事件处理、数据库连接与跨平台打包等核心技能,通过多个桌面应用项目实战,帮助学员快速掌握 Qt 框架并独立完成跨平台GUI软件的开发。

4042

2025.08.15

C++桌面程序开发
C++桌面程序开发

本专题聚焦 C++ 在桌面端图形界面应用开发中的实战应用,系统讲解 Qt 框架的信号与槽机制、界面布局管理、事件响应、数据交互、样式美化与多窗口应用设计等核心知识。通过实战案例(如记事本应用、数据管理工具、系统监控面板),帮助学习者掌握 从UI设计到完整桌面软件开发的C++工程化能力。

1194

2025.10.23

C++ 图形界面开发基础(Qt方向)
C++ 图形界面开发基础(Qt方向)

本专题系统讲解 使用 C++ 与 Qt 进行图形界面(GUI)开发的核心技能,内容涵盖 Qt 项目结构、窗口组件、信号与槽机制、事件处理、布局管理、资源管理,以及跨平台编译与打包流程。通过多个小型桌面应用实战案例,帮助学习者掌握从界面设计到功能实现的完整 GUI 开发能力。

1401

2025.12.05

string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

5539

2023.08.02

int占多少字节
int占多少字节

int占4个字节,意味着一个int变量可以存储范围在-2,147,483,648到2,147,483,647之间的整数值,在某些情况下也可能是2个字节或8个字节,int是一种常用的数据类型,用于表示整数,需要根据具体情况选择合适的数据类型,以确保程序的正确性和性能。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2785

2024.08.29

c++怎么把double转成int
c++怎么把double转成int

本专题整合了 c++ double相关教程,阅读专题下面的文章了解更多详细内容。

3448

2025.08.29

C++中int的含义
C++中int的含义

本专题整合了C++中int相关内容,阅读专题下面的文章了解更多详细内容。

2465

2025.08.29

lambda表达式
lambda表达式

Lambda表达式是一种匿名函数的简洁表示方式,它可以在需要函数作为参数的地方使用,并提供了一种更简洁、更灵活的编码方式,其语法为“lambda 参数列表: 表达式”,参数列表是函数的参数,可以包含一个或多个参数,用逗号分隔,表达式是函数的执行体,用于定义函数的具体操作。本专题为大家提供lambda表达式相关的文章、下载、课程内容,供大家免费下载体验。

891

2023.09.15

LLVM自定义Pass怎么写
LLVM自定义Pass怎么写

本专题聚焦LLVM自定义Pass开发,整理Pass类结构、run()方法、PreservedAnalyses、CMake构建、插件注册、-load-pass-plugin加载和测试用例编写流程。

20

2026.09.30

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Conan 2 Essentials 免费课程
Conan 2 Essentials 免费课程

共0课时 | 0人学习

CMake 与 Conan 集成实践
CMake 与 Conan 集成实践

共0课时 | 0人学习

Conan 2 高级依赖模型介绍
Conan 2 高级依赖模型介绍

共0课时 | 0人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn