最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

使用C++實(shí)現(xiàn)類似Qt的信號(hào)與槽機(jī)制功能

 更新時(shí)間:2025年01月02日 09:57:56   作者:極客晨風(fēng)  
信號(hào)與槽機(jī)制是 Qt 框架中的核心設(shè)計(jì),用于實(shí)現(xiàn)對(duì)象之間的解耦通信,在純 C++ 中,我們也可以設(shè)計(jì)出類似的機(jī)制,利用模板、函數(shù)指針和哈希表,實(shí)現(xiàn)高效且靈活的信號(hào)與槽功能,本文給大家介紹了如何使用C++實(shí)現(xiàn)類似Qt的信號(hào)與槽機(jī)制功能,需要的朋友可以參考下

1. 什么是信號(hào)與槽?

信號(hào)與槽是一個(gè)發(fā)布-訂閱模式的變種。我們可以將它理解為:

  • 信號(hào): 一個(gè)事件源(Publisher),當(dāng)某個(gè)事件發(fā)生時(shí),它會(huì)觸發(fā)(emit)信號(hào)。
  • 槽: 一個(gè)事件處理器(Subscriber),當(dāng)信號(hào)觸發(fā)時(shí),它會(huì)被調(diào)用,完成具體的響應(yīng)任務(wù)。

例如:

  • 一個(gè)按鈕點(diǎn)擊時(shí)發(fā)出信號(hào),槽函數(shù)負(fù)責(zé)處理點(diǎn)擊事件。
  • 一個(gè)定時(shí)器觸發(fā)信號(hào),槽函數(shù)完成定時(shí)任務(wù)。

在 C++ 中,我們可以用模板和函數(shù)對(duì)象來(lái)模擬這種機(jī)制。

2. 設(shè)計(jì)目標(biāo)

實(shí)現(xiàn)的功能

  1. 允許多個(gè)槽連接到同一個(gè)信號(hào)。
  2. 支持動(dòng)態(tài)添加和移除槽。
  3. 觸發(fā)信號(hào)時(shí),自動(dòng)調(diào)用所有已連接的槽。
  4. 使用模板支持不同的信號(hào)參數(shù)類型。
  5. 靈活注冊(cè)普通函數(shù)、類成員函數(shù)和 Lambda 表達(dá)式作為槽。

3. 模塊設(shè)計(jì)

(1)Signal 模板類

Signal 是我們?cè)O(shè)計(jì)的核心類,用于管理信號(hào)與槽的連接和觸發(fā)。它需要實(shí)現(xiàn)以下功能:

  • connect 注冊(cè)一個(gè)槽函數(shù)到信號(hào)。
  • disconnect 通過(guò)唯一 ID 動(dòng)態(tài)移除槽函數(shù)。
  • emit 觸發(fā)信號(hào),調(diào)用所有已注冊(cè)的槽。

下面是 Signal 類的完整實(shí)現(xiàn):

#ifndef SIGNAL_H
#define SIGNAL_H

#include <unordered_map>   // 用于存儲(chǔ)槽的哈希表
#include <functional>      // 用于存儲(chǔ)任意形式的槽函數(shù)
#include <iostream>        // 用于輸出調(diào)試信息

// 信號(hào)類
template <typename... Args>
class Signal {
public:
    using SlotType = std::function<void(Args...)>; // 定義槽的類型
    using SlotID = int;                           // 槽的唯一標(biāo)識(shí)符

    // 連接一個(gè)槽,返回槽的唯一 ID
    SlotID connect(SlotType slot) {
        SlotID id = nextID++;
        slots[id] = slot; // 將槽存入哈希表
        return id;
    }

    // 斷開(kāi)一個(gè)槽,通過(guò)其唯一 ID
    void disconnect(SlotID id) {
        auto it = slots.find(id);
        if (it != slots.end()) {
            slots.erase(it); // 從哈希表中移除槽
        }
    }

    // 觸發(fā)信號(hào),調(diào)用所有已連接的槽
    void emit(Args... args) const {
        for (const auto &pair : slots) {
            pair.second(args...); // 調(diào)用槽函數(shù)
        }
    }

private:
    std::unordered_map<SlotID, SlotType> slots; // 存儲(chǔ)槽的哈希表
    SlotID nextID = 0;                          // 用于生成唯一 ID 的計(jì)數(shù)器
};

#endif // SIGNAL_H

(2)連接槽的示例

我們使用 Signal 模板類連接多個(gè)槽,包括普通函數(shù)、Lambda 表達(dá)式和類成員函數(shù)。

#include "Signal.h"
#include <iostream>
#include <string>

// 普通函數(shù)作為槽
void slot1(const std::string &message) {
    std::cout << "槽1 收到消息: " << message << std::endl;
}

// 普通函數(shù)作為槽
void slot2(const std::string &message) {
    std::cout << "槽2 收到消息: " << message << std::endl;
}

// 測(cè)試類,擁有自己的槽
class TestClass {
public:
    // 成員函數(shù)作為槽
    void classSlot(const std::string &message) {
        std::cout << "TestClass::classSlot 收到消息: " << message << std::endl;
    }
};

(3)主程序示例

通過(guò)主程序,我們測(cè)試以下功能:

  • 注冊(cè)普通函數(shù)、Lambda 表達(dá)式和成員函數(shù)到信號(hào)。
  • 觸發(fā)信號(hào),調(diào)用所有槽。
  • 動(dòng)態(tài)斷開(kāi)某個(gè)槽,驗(yàn)證槽移除功能。
#include "Signal.h"
#include <iostream>
#include <string>

int main() {
    // 創(chuàng)建一個(gè)信號(hào)
    Signal<std::string> signal;

    // 連接普通函數(shù)到信號(hào)
    auto id1 = signal.connect(slot1);
    auto id2 = signal.connect(slot2);

    // 創(chuàng)建一個(gè)類實(shí)例,并連接成員函數(shù)到信號(hào)
    TestClass obj;
    auto id3 = signal.connect([&obj](const std::string &message) {
        obj.classSlot(message);
    });

    // 第一次觸發(fā)信號(hào),所有槽都會(huì)被調(diào)用
    std::cout << "第一次觸發(fā)信號(hào):" << std::endl;
    signal.emit("你好,信號(hào)與槽!");

    // 從信號(hào)中斷開(kāi)槽1
    std::cout << "\n斷開(kāi)槽1后,第二次觸發(fā)信號(hào):" << std::endl;
    signal.disconnect(id1);

    // 第二次觸發(fā)信號(hào),僅槽2和成員函數(shù)槽會(huì)被調(diào)用
    signal.emit("這是第二條消息!");

    return 0;
}

4. 運(yùn)行結(jié)果

運(yùn)行程序后,輸出如下:

第一次觸發(fā)信號(hào):
槽1 收到消息: 你好,信號(hào)與槽!
槽2 收到消息: 你好,信號(hào)與槽!
TestClass::classSlot 收到消息: 你好,信號(hào)與槽!

斷開(kāi)槽1后,第二次觸發(fā)信號(hào):
槽2 收到消息: 這是第二條消息!
TestClass::classSlot 收到消息: 這是第二條消息!

5. 代碼解析

  1. 槽的管理

    • 每個(gè)槽函數(shù)通過(guò) connect 方法注冊(cè)到信號(hào),信號(hào)會(huì)為每個(gè)槽分配一個(gè)唯一標(biāo)識(shí)符(SlotID)。
    • 槽函數(shù)存儲(chǔ)在 std::unordered_map 中,鍵為 SlotID,值為槽函數(shù)。
  2. 信號(hào)的觸發(fā)

    • 調(diào)用 emit 方法時(shí),會(huì)遍歷所有注冊(cè)的槽,并依次調(diào)用它們。
  3. 槽的動(dòng)態(tài)移除

    • 通過(guò)槽的唯一標(biāo)識(shí)符(SlotID),調(diào)用 disconnect 方法,可以從信號(hào)中移除指定的槽。
  4. 支持多種類型的槽

    • 使用 std::function 存儲(chǔ)槽,可以輕松支持普通函數(shù)、Lambda 表達(dá)式和類成員函數(shù)。

6. 特點(diǎn)與優(yōu)點(diǎn)

優(yōu)點(diǎn)

  1. 模塊化設(shè)計(jì):
    • Signal 類實(shí)現(xiàn)信號(hào)的管理與觸發(fā),獨(dú)立、易用。
  2. 支持多樣化槽:
    • 既支持普通函數(shù),又支持成員函數(shù)和 Lambda 表達(dá)式。
  3. 高性能:
    • 使用 std::unordered_map 存儲(chǔ)槽,添加、移除和觸發(fā)的時(shí)間復(fù)雜度為 O(1)。

特點(diǎn)

  • 輕量級(jí)實(shí)現(xiàn): 僅依賴 C++ 標(biāo)準(zhǔn)庫(kù),無(wú)需額外框架。
  • 模板化設(shè)計(jì): 可以適配任意參數(shù)類型的信號(hào)與槽。

7. 應(yīng)用場(chǎng)景

  1. 事件驅(qū)動(dòng)開(kāi)發(fā):
    • 如 GUI 按鈕點(diǎn)擊、窗口關(guān)閉事件等場(chǎng)景。
  2. 解耦模塊:
    • 觀察者模式中,用信號(hào)與槽代替觀察者通知機(jī)制。
  3. 回調(diào)機(jī)制:
    • 替代傳統(tǒng)的回調(diào)函數(shù)方式,提供更靈活的信號(hào)與槽功能。

8. 總結(jié)

通過(guò)本文,我們實(shí)現(xiàn)了一個(gè)輕量級(jí)、功能完善的信號(hào)與槽系統(tǒng)。它借鑒了 Qt 的設(shè)計(jì)思想,但更加輕量化和靈活。這個(gè)設(shè)計(jì)可以輕松應(yīng)用于任意純 C++ 項(xiàng)目,特別適合事件驅(qū)動(dòng)和解耦通信的場(chǎng)景。如果需要擴(kuò)展到多線程環(huán)境,可以在此基礎(chǔ)上加入線程安全機(jī)制,如 std::mutex。

你可以將此代碼作為基礎(chǔ),進(jìn)一步改造和優(yōu)化,打造符合你需求的高效信號(hào)與槽系統(tǒng)!

到此這篇關(guān)于使用C++實(shí)現(xiàn)類似Qt的信號(hào)與槽機(jī)制功能的文章就介紹到這了,更多相關(guān)C++實(shí)現(xiàn)信號(hào)與槽機(jī)制內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C# 使用反射來(lái)實(shí)現(xiàn)對(duì)象的深度復(fù)制方法

    C# 使用反射來(lái)實(shí)現(xiàn)對(duì)象的深度復(fù)制方法

    下面小編就為大家?guī)?lái)一篇C# 使用反射來(lái)實(shí)現(xiàn)對(duì)象的深度復(fù)制方法。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-01-01
  • C++Primer筆記之順序容器的使用詳解

    C++Primer筆記之順序容器的使用詳解

    本篇文章對(duì)C++Primer 順序容器的使用進(jìn)行了詳細(xì)的分析介紹。需要的朋友參考下
    2013-05-05
  • C語(yǔ)言文件打開(kāi)的模式

    C語(yǔ)言文件打開(kāi)的模式

    這篇文章主要介紹了C語(yǔ)言文件打開(kāi)的模式,以及相關(guān)的原理和知識(shí)點(diǎn)做了分享,有興趣的朋友參考學(xué)習(xí)下。
    2018-03-03
  • 詳解如何在C/C++中測(cè)量一個(gè)函數(shù)或功能的運(yùn)行時(shí)間

    詳解如何在C/C++中測(cè)量一個(gè)函數(shù)或功能的運(yùn)行時(shí)間

    本文算是一個(gè)比較完整的關(guān)于在 C/C++ 中測(cè)量一個(gè)函數(shù)或者功能的總結(jié),最后會(huì)演示三種方法的對(duì)比,文章通過(guò)代碼示例給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2023-12-12
  • C語(yǔ)言實(shí)現(xiàn)個(gè)人財(cái)務(wù)管理

    C語(yǔ)言實(shí)現(xiàn)個(gè)人財(cái)務(wù)管理

    這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)個(gè)人財(cái)務(wù)管理,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-11-11
  • 詳細(xì)分析C++ 多態(tài)和虛函數(shù)

    詳細(xì)分析C++ 多態(tài)和虛函數(shù)

    這篇文章主要介紹了C++ 多態(tài)和虛函數(shù)的相關(guān)資料,文中示例代碼非常詳細(xì),幫助大家更好的理解和學(xué)習(xí),感興趣的朋友可以了解下
    2020-07-07
  • 關(guān)于C語(yǔ)言中數(shù)據(jù)在內(nèi)存中的存儲(chǔ)詳解

    關(guān)于C語(yǔ)言中數(shù)據(jù)在內(nèi)存中的存儲(chǔ)詳解

    這篇文章主要給大家介紹了關(guān)于C語(yǔ)言中數(shù)據(jù)在內(nèi)存中的存儲(chǔ)的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-04-04
  • C++的optional用法實(shí)例詳解

    C++的optional用法實(shí)例詳解

    編程中我們可能會(huì)遇到要處理可能為空的變量,比如說(shuō)容器,基本類型,或者說(shuō)對(duì)象實(shí)例,下面通過(guò)實(shí)例代碼介紹C++的optional用法,感興趣的朋友一起看看吧
    2024-02-02
  • 詳解C++11 原始字符串字面量(Json字符串表達(dá)更方便)

    詳解C++11 原始字符串字面量(Json字符串表達(dá)更方便)

    原始字符串字面量(Raw String Literal)是C++11引入的一種字符串表示方式,用于簡(jiǎn)化字符串的定義,特別是當(dāng)字符串中包含大量特殊字符(如換行符、雙引號(hào)等)時(shí),這篇文章給大家介紹C++11原始字符串字面量(Json字符串表達(dá)更方便)的相關(guān)知識(shí),感興趣的朋友一起看看吧
    2025-03-03
  • C++中構(gòu)造函數(shù)與析構(gòu)函數(shù)的調(diào)用順序詳解

    C++中構(gòu)造函數(shù)與析構(gòu)函數(shù)的調(diào)用順序詳解

    C++ 語(yǔ)言一直被批評(píng)太復(fù)雜了,很多細(xì)節(jié)的地方需要仔細(xì)推敲,甚至其構(gòu)造函數(shù)和析構(gòu)的調(diào)用順序也成為了一個(gè)讓人迷惑的問(wèn)題,在此我做了簡(jiǎn)單的總結(jié)。這篇文章主要介紹了C++中構(gòu)造函數(shù)與析構(gòu)函數(shù)的調(diào)用順序,需要的朋友可以參考借鑒。
    2017-01-01

最新評(píng)論

司法| 汤阴县| 德庆县| 长宁县| 临高县| 林芝县| 芜湖市| 宜良县| 公安县| 司法| 万全县| 玉环县| 始兴县| 广安市| 宜川县| 进贤县| 宝坻区| 鹤壁市| 洪湖市| 浦东新区| 东乡| 富川| 泰和县| 南川市| 原平市| 莫力| 广东省| 白河县| 修文县| 容城县| 海伦市| 安福县| 涿鹿县| 常宁市| 汶上县| 满洲里市| 思茅市| 岳阳县| 斗六市| 兰坪| 永胜县|