IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> Qt--通过观察者模式实现信号槽 -> 正文阅读

[C++知识库]Qt--通过观察者模式实现信号槽

前提:1.熟悉了观察者模式,不熟悉看这个观察者模式
2.了解Qt的信号和信号槽。
3.熟悉std::bind()来调用类的方法std::bind调用类方法
4.熟悉模板类的简单使用模板类做基类

1.Qt中的信号和信号槽

  • 在Qt中-----准备工作
    1.定义A对象, 定义A对象的信号signal-A
    2.定义B对象,定义B对象的slot函数
    3.connect函数:将A对象发出的signal-A, 和B对象执行的slot函数绑定起来。
  • 信号触发
    4.A发出信号signal-A
    5.B收到signal-A就会执行slot函数

2.本质的解析

3.connect函数执行的动作:其实就是一个B对象订阅signal-A的动作。
4.A发出信号:即代表一个广播的动作,但只有B对象会处理这个信号,因为B对象有订阅这个信号。
5.B收到信号的处理动作,即执行slot()函数

上面的三点加起来就是:消息的订阅,消息的发布,消息的处理。这就是一个观察者模式。

3.通过观察者模式实现信号槽

假设这样一个场景:猫和老鼠的tom和jerry
1.jerry看着tom.
2.tom叫
3.jerry跑
上面三个对应:订阅,发布,处理。即Qt 的connect(), emit ,slot函数

#include "Subject.h"
#include <functional>
#include <iostream>

using std::cout;
using std::endl;

class catObserver {
public:
    virtual void onPublish() = 0;
public:
    virtual ~catObserver() {} // 避免内存泄漏
};


class Jerry : public catObserver {
public:
    void onPublish() { // 3.jerry听到tom叫执行的动作
        Run();
    }  

private:
    void Run() {
        cout << "hear tom miao,jerry run" << endl;
    }
};

class Tom {
public:
    void subscribe(catObserver* observer) {
        // subscribe jerry
        obj_list.push_back(observer);
    }
    void publish() {
        cout << "tom miao" << endl;
        for (auto tmp: obj_list) {
            tmp->onPublish();
        }
    }

    // 
private:
    // subscriber list
    std::vector<catObserver* > obj_list;
};


int main()
{
    Tom tom;
    Jerry jerry;
    //1. jerry 看着tom
    tom.subscribe(&jerry);
    //2.tom 叫
    tom.publish();
    return 0;
}

//上面的代码简单的实现了:消息的订阅,发布,和处理。而QT的信号槽不过是观察者模式的升级。
QT的connect() -----------------观察者模式的订阅,把消息和处理函数绑定起来(通过catObserver的虚方法的实现)
QT的emit某个signal ----------观察者模式的消息发布
QT的信号槽函数---------------观察者模式的消息处理

简单的封装带有publish,subscribe的基类

// VistorMode.h
#include <vector>
#include <algorithm>


//一个带有订阅。发布的基础类
template <typename ObserverType>
class Subject
{
public:
    // void subscribe(catObserver* observer)
/*希望subscribe的传参是任何类型的观察者,所以不能是catObserver,
希望在不同的子类定义的时候去定义子类,比如猫tom就应该传入catObserver
比如狗dog就该传入dogObserver,所以传入subscribe的参数是模板类型ObserverType
*/
    void subscribe(ObserverType* obsver)
    {
        auto tmp = std::find(obj_list.begin(), obj_list.end(), obsver);
        if (tmp == obj_list.end()) {
            obj_list.push_back(obsver);
        }
    }

    void unsubscribe(ObserverType* obsver)
    {
        obj_list.erase(std::remove(obj_list.begin(), obj_list.end(), obsver));
    }
    //执行obj_list里面对应的回调函数,比如上面的catObserver->onPublish(),
    //希望可以执行任意形式的回调函数
    template <typename FuncType>
    void publish(FuncType func)
    {
        for (auto obs: obj_list)
        {
            //调用回调函数,将obs作为第一个参数传递,否则类的方法不可调用
            func(obs);
        } 
    }

private:
    std::vector<ObserverType*> obj_list;
};

// #include "Subject.h"
#include "VistorMode.h"
#include <functional>
#include <iostream>


using std::cout;
using std::endl;
using std::bind;

class catObserver {
public:
    virtual void onMiao() = 0;
public:
    virtual ~catObserver() {} // 避免内存泄漏
};


class Jerry : public catObserver {
public:
    void onMiao() { // 3.jerry听到tom叫执行的动作,需要在tom的publish去调用
        Run();
    }  

private:
    void Run() {
        cout << "hear tom miao,jerry run" << endl;
    }
};



class Tom : public Subject<catObserver>
{
public:
    void Miao() {
        publish(std::bind(&catObserver::onMiao, std::placeholders::_1));
    }
};


int main()
{
    Tom tom;
    Jerry jerry;
    //1. jerry 看着tom
    tom.subscribe(&jerry);
    //2.tom 叫
    tom.Miao();
    return 0;
}
  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-04-18 17:22:53  更:2022-04-18 17:23:04 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 0:07:58-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码