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

C++怎么实现观察者模式_C++事件机制教程【解耦】

云辰同学_4471

云辰同学_4471

发布时间:2026-02-27 12:36:41

|

955人浏览过

|

来源于php中文网

原创

用 std::function + std::vector 可实现轻量观察者模式,核心是运行时回调抽象与安全生命周期管理,避免虚函数耦合和悬挂调用。

c++怎么实现观察者模式_c++事件机制教程【解耦】

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

不用第三方库、不依赖 Qt 或 Boost,纯标准 C++ 就能搭出可用的观察者链。核心是把回调抽象成 std::function<void></void>(或带参数的变体),用 std::vector 存储,触发时遍历调用。

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

  • 推荐签名:using Callback = std::function<void event>;</void>,Event 是自定义结构体,比 void* 安全、比模板泛型易维护
  • 注册时别写 obs.register([]{ /* 用局部变量 */ }); —— 捕获栈变量的 lambda 一出作用域就失效
  • 移除回调不能只靠 erase 迭代器,得配套实现 ID 或比较逻辑,否则无法安全解绑

为什么不用虚函数多态实现 Observer 接口

传统教科书写法是定义 Observer 抽象基类,让具体类继承并重写 update()。这在 C++ 里容易引发两个实际问题:内存布局耦合和销毁顺序风险。

当被观察者持有 std::vector<:unique_ptr>></:unique_ptr>,而某个 Observer 子类对象自身又持有被观察者引用(比如 UI 控件监听数据模型),就极易形成循环引用或析构时访问已释放内存。用 std::function 则天然解耦类型,回调绑定发生在运行时,不强制继承关系。

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

  • 虚函数方案要求所有观察者从同一基类派生,限制了现有类的复用(比如你不能让一个 std::thread 对象直接当 observer)
  • 虚表指针带来微小但确定的内存与调用开销;std::function 在 clang/gcc 下对空捕获 lambda 通常内联为直接调用
  • 调试时,虚函数调用栈深、符号模糊;std::function 调用点清晰,gdb 里能直接看到注册位置

std::weak_ptr 配合 std::shared_ptr 解决悬挂回调

最常被忽略的坑:UI 控件作为观察者被销毁了,但被观察者还留着它的 std::function 回调,下次通知直接 crash。解决方案不是禁止销毁,而是让回调“知道自己是否还有效”。

C++14
C++14

C++14 对 C++11 的修正与增强版本,适合旧系统维护和较老工具链兼容。

下载

做法是观察者对象用 std::shared_ptr 管理,注册时传入 std::weak_ptr 包装的 lambda:

auto self = shared_from_this();
obs.register([self](const Event& e) {
    if (auto ptr = self.lock()) {
        ptr->handle(e);
    } // 否则静默丢弃
});

这要求观察者类继承 std::enable_shared_from_this,且必须由 std::make_shared 构造。硬伤是:不能用于栈对象或全局对象——它们根本没法套 shared_ptr。

  • 别试图用 std::weak_ptr 包裹 std::function 本身——std::function 不支持 weak 语义
  • 如果观察者是普通类实例(非 shared_ptr 管理),只能靠手动 unregister,且必须保证 unregister 调用早于对象析构
  • Qt 的 QObject::connect 默认做类似 weak 检查,但那是元对象系统 baked in 的行为,标准 C++ 得自己铺路

性能敏感场景下避免 std::function 的堆分配

每次 std::function 构造都可能触发一次小内存分配(尤其捕获较多变量时),高频事件(如帧更新、音频采样)中会明显拖慢吞吐。这时候得降级到函数指针 + void* 上下文,或用 std::variant 预设几种回调形态。

更务实的做法是:先用 std::function 快速验证逻辑,再针对 hot path 优化。例如把最常用的无参回调单独抽成 std::array<:function>, 8></:function>,固定大小避免动态扩容。

  • Clang/GCC 对空捕获 lambda 转 std::function 通常零开销;但捕获 3 个以上变量,大概率触发堆分配
  • 用 sizeof(std::function<void>) == 32</void>(常见值)可粗略判断是否溢出 small buffer optimization
  • 别过早优化:95% 的业务事件(配置变更、网络响应)完全不需要考虑这点,先跑通再测

真正难的从来不是怎么写完一个观察者,而是想清楚谁拥有谁、谁决定谁的生命周期、以及通知失败时要不要重试或丢弃——这些不会出现在类图里,但每一条都直接对应 core dump 或数据不一致。

热门AI工具

更多
PixPix
PixPix Hot

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

立刻MV
立刻MV Hot

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

WorkBuddy

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

讯飞绘文

讯飞绘文是一款由科大讯飞推出的一站式 AIGC 内容运营平台。

豆包大模型

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

DeepSeek

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

咔片AIPPT

一款在线AI演示文稿制作工具,可根据主题和内容需求辅助生成PPT结构与页面,提高演示材料制作效率。

Lovart
Lovart Hot

一款面向视觉设计创作的AI设计平台,可通过智能体和画布工作流辅助制作海报、Logo、网页、PPT及其他视觉内容。

蛙蛙写作

一款AI论文写作工具,主要用于超级AI智能写作助手,适合需要提升相关任务效率的用户。

相关专题

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

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

4662

2025.08.15

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

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

1294

2025.10.23

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

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

1421

2025.12.05

java多态详细介绍
java多态详细介绍

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

335

2025.11.27

java多态详细介绍
java多态详细介绍

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

335

2025.11.27

golang结构体相关大全
golang结构体相关大全

本专题整合了golang结构体相关大全,想了解更多内容,请阅读专题下面的文章。

4574

2025.06.09

golang结构体方法
golang结构体方法

本专题整合了golang结构体相关内容,请阅读专题下面的文章了解更多。

4731

2025.07.04

javascriptvoid(o)怎么解决
javascriptvoid(o)怎么解决

javascriptvoid(o)的解决办法:1、检查语法错误;2、确保正确的执行环境;3、检查其他代码的冲突;4、使用事件委托;5、使用其他绑定方式;6、检查外部资源等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

636

2023.11.23

Linux 新手先学哪些命令
Linux 新手先学哪些命令

Linux新手命令专题汇集终端基础、文件目录操作、文本查看、软件安装和权限管理等入门文章,帮助按实际任务练习常用命令并建立命令行操作习惯。

0

2026.10.15

热门下载

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

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
C++ Core Guidelines
C++ Core Guidelines

共0课时 | 0人学习

C++ Reference
C++ Reference

共0课时 | 0人学习

C++ 官方标准说明
C++ 官方标准说明

共0课时 | 0人学习

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

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