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

怎样实现C++中的观察者模式 信号槽机制与现代事件系统设计

云枫君_6741

云枫君_6741

发布时间:2025-08-13 13:59:01

|

375人浏览过

|

来源于php中文网

原创

观察者模式的实现可通过传统方法、信号槽机制或现代事件系统完成。1. 传统方法需手动管理观察者列表,包含主题、观察者、具体主题和具体观察者四个核心部分;2. 信号槽机制如qt的实现,通过connect连接信号与槽函数,自动处理通知流程,简化了观察者管理;3. 现代事件系统使用eventmanager和std::function支持多种事件类型,提供更高的灵活性和扩展性;4. 实现方式的选择取决于项目需求,qt适合已集成环境,事件系统适合需要多类型事件处理场景,而简单项目可采用传统方式。

怎样实现C++中的观察者模式 信号槽机制与现代事件系统设计

观察者模式是一种行为设计模式,它允许一个对象(称为主题)维护一个依赖它的对象列表(称为观察者),并在主题状态发生改变时自动通知所有观察者。C++中实现观察者模式,可以借助信号槽机制或者现代事件系统设计,但核心在于解耦主题和观察者。

怎样实现C++中的观察者模式 信号槽机制与现代事件系统设计

解决方案

怎样实现C++中的观察者模式 信号槽机制与现代事件系统设计

实现观察者模式,通常需要以下几个关键组成部分:

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

  1. 主题(Subject): 维护观察者列表,提供添加、删除观察者的接口,并在状态改变时通知观察者。
  2. 观察者(Observer): 定义一个更新接口,用于接收主题的通知。
  3. 具体主题(Concrete Subject): 主题的具体实现,包含状态,并在状态改变时调用通知方法。
  4. 具体观察者(Concrete Observer): 观察者的具体实现,实现更新接口,并在接收到通知后执行相应的操作。

下面是一个简单的C++代码示例:

怎样实现C++中的观察者模式 信号槽机制与现代事件系统设计
#include <iostream>
#include <vector>

class Observer {
public:
    virtual void update(int state) = 0;
};

class Subject {
public:
    virtual void attach(Observer* observer) {
        observers_.push_back(observer);
    }

    virtual void detach(Observer* observer) {
        for (auto it = observers_.begin(); it != observers_.end(); ++it) {
            if (*it == observer) {
                observers_.erase(it);
                return;
            }
        }
    }

    virtual void notify() {
        for (Observer* observer : observers_) {
            observer->update(state_);
        }
    }

    void setState(int state) {
        state_ = state;
        notify();
    }

private:
    std::vector<Observer*> observers_;
protected:
    int state_;
};

class ConcreteObserver : public Observer {
public:
    ConcreteObserver(Subject* subject, int id) : subject_(subject), id_(id) {}

    void update(int state) override {
        state_ = state;
        std::cout << "Observer " << id_ << " received update. New state: " << state_ << std::endl;
    }

private:
    Subject* subject_;
    int state_;
    int id_;
};

int main() {
    Subject subject;
    ConcreteObserver observer1(&subject, 1);
    ConcreteObserver observer2(&subject, 2);

    subject.attach(&observer1);
    subject.attach(&observer2);

    subject.setState(10);
    subject.setState(20);

    subject.detach(&observer2);
    subject.setState(30);

    return 0;
}

这个例子展示了基本的观察者模式实现。接下来,我们讨论如何使用信号槽机制和现代事件系统来改进它。

C++ 算法竞赛自动化测试数据生成与校验框架
C++ 算法竞赛自动化测试数据生成与校验框架

根据原题生成新题面、验证器及完整测试数据,自动套用 testlib 模板,用于用户要求生成测试数据时。

下载

信号槽机制如何简化观察者模式的实现?

信号槽机制,例如Qt中的信号槽,提供了一种类型安全、松耦合的方式来实现观察者模式。不再需要手动管理观察者列表,信号槽机制会自动处理连接和断开,以及参数传递。

例如,使用Qt的信号槽:

#include <QObject>
#include <QDebug>

class MySubject : public QObject {
    Q_OBJECT

public:
    MySubject(QObject *parent = nullptr) : QObject(parent) {}

    void setState(int state) {
        state_ = state;
        emit stateChanged(state_);
    }

signals:
    void stateChanged(int newState);

private:
    int state_;
};

class MyObserver : public QObject {
    Q_OBJECT

public:
    MyObserver(QObject *parent = nullptr) : QObject(parent) {}

public slots:
    void handleStateChanged(int newState) {
        qDebug() << "Observer received new state:" << newState;
    }
};

int main(int argc, char *argv[]) {
    QCoreApplication a(argc, argv);

    MySubject subject;
    MyObserver observer;

    QObject::connect(&subject, &MySubject::stateChanged, &observer, &MyObserver::handleStateChanged);

    subject.setState(42);
    subject.setState(99);

    return a.exec();
}

#include "main.moc" // Important: Include the generated moc file

这个例子中,

stateChanged
是一个信号,
handleStateChanged
是一个槽。
QObject::connect
函数将信号和槽连接起来。当
subject.setState()
被调用时,
stateChanged
信号会被发射,从而自动调用
observer.handleStateChanged()
。 注意,Qt需要 moc (Meta-Object Compiler) 来处理
Q_OBJECT
宏,生成必要的元对象代码。

现代事件系统设计如何提升观察者模式的灵活性?

现代事件系统,通常采用更灵活的设计,例如允许传递任意类型的事件数据,支持事件过滤和优先级,以及提供更高级的事件路由机制。

一个简单的事件系统可以基于函数指针或

std::function
实现。

#include <iostream>
#include <functional>
#include <vector>
#include <algorithm>

class Event {
public:
    virtual ~Event() = default;
};

template <typename T>
class TypedEvent : public Event {
public:
    TypedEvent(T data) : data_(data) {}

    T getData() const { return data_; }

private:
    T data_;
};


class EventManager {
public:
    template <typename T>
    void subscribe(std::function<void(T)> handler) {
        handlers_.push_back([handler](Event* event) {
            if (auto typedEvent = dynamic_cast<TypedEvent<T>*>(event)) {
                handler(typedEvent->getData());
            }
        });
    }

    void publish(Event* event) {
        for (auto& handler : handlers_) {
            handler(event);
        }
        delete event; // Important:  Manage event lifetime
    }

private:
    std::vector<std::function<void(Event*)>> handlers_;
};

int main() {
    EventManager eventManager;

    // Subscribe to integer events
    eventManager.subscribe<int>([](int data) {
        std::cout << "Integer event received: " << data << std::endl;
    });

    // Subscribe to string events
    eventManager.subscribe<std::string>([](std::string data) {
        std::cout << "String event received: " << data << std::endl;
    });

    // Publish events
    eventManager.publish(new TypedEvent<int>(123));
    eventManager.publish(new TypedEvent<std::string>("Hello, Event System!"));
    eventManager.publish(new TypedEvent<int>(456));


    return 0;
}

这个例子中,

EventManager
允许订阅不同类型的事件,并使用
std::function
来处理事件。
TypedEvent
用于携带特定类型的数据。 关键在于
dynamic_cast
,它允许我们安全地将
Event*
转换为
TypedEvent<T>*
,并提取数据。 注意事件的生命周期管理,
publish
函数负责删除事件。

如何选择合适的观察者模式实现方式?

选择哪种实现方式取决于项目的具体需求。如果项目已经使用了Qt,那么使用Qt的信号槽机制是最自然的选择。如果需要更灵活的事件系统,可以考虑基于

std::function
实现自定义的事件系统。对于简单的观察者模式,手动管理观察者列表也是一个可行的选择。 关键在于理解不同实现方式的优缺点,并选择最适合项目需求的方案。

热门AI工具

更多
豆包大模型

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

AionClaw
AionClaw Hot

AionClaw是一款面向办公、创作和编程任务的AI桌面智能体。

二狗PPT
二狗PPT Hot

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

火山引擎

火山引擎是一款面向企业的云计算与AI服务平台。

DeepSeek

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

立刻MV
立刻MV Hot

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

WorkBuddy

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

Lovart
Lovart Hot

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

讯飞智作

讯飞智作是一款AI视频创作工具,AI文本配音工具,数字人课程、营销视频制作。

相关专题

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

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

3662

2025.08.15

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

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

1114

2025.10.23

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

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

1341

2025.12.05

C++ 智能指针与现代内存管理
C++ 智能指针与现代内存管理

深入讲解 C++ 现代内存管理的核心工具——智能指针,涵盖 unique_ptr 独占所有权语义、shared_ptr 引用计数机制与循环引用问题、weak_ptr 弱引用的应用场景、make_unique/make_shared 工厂函数的性能优势、自定义删除器的编写、RAII 资源管理思想的实践,以及从裸指针迁移到智能指针的重构策略,帮助开发者编写安全无泄漏的现代 C++ 代码。

299

2026.04.23

硬盘接口类型介绍
硬盘接口类型介绍

硬盘接口类型有IDE、SATA、SCSI、Fibre Channel、USB、eSATA、mSATA、PCIe等等。详细介绍:1、IDE接口是一种并行接口,主要用于连接硬盘和光驱等设备,它主要有两种类型:ATA和ATAPI,IDE接口已经逐渐被SATA接口;2、SATA接口是一种串行接口,相较于IDE接口,它具有更高的传输速度、更低的功耗和更小的体积;3、SCSI接口等等。

3028

2023.10.19

PHP接口编写教程
PHP接口编写教程

本专题整合了PHP接口编写教程,阅读专题下面的文章了解更多详细内容。

4249

2025.10.17

php8.4实现接口限流的教程
php8.4实现接口限流的教程

PHP8.4本身不内置限流功能,需借助Redis(令牌桶)或Swoole(漏桶)实现;文件锁因I/O瓶颈、无跨机共享、秒级精度等缺陷不适用高并发场景。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

3649

2025.12.29

java接口相关教程
java接口相关教程

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

366

2026.01.19

Buffalo框架数据库开发全教程
Buffalo框架数据库开发全教程

本专题围绕Buffalo框架数据库开发,讲解database.yml多环境配置、soda与fizz迁移生成回滚、模型结构体标签、增删改查与条件查询、一对多与多对多关联、数据校验、回调钩子、事务处理及原生SQL执行能力。

20

2026.09.23

热门下载

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

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
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