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

C++11 寫一個(gè)只觸發(fā)一次槽函數(shù)的Qt connect函數(shù)

 更新時(shí)間:2022年09月09日 11:28:33   作者:manxisuo  
這篇文章主要為大家介紹了C++11 寫一個(gè)只觸發(fā)一次槽函數(shù)的Qt connect函數(shù)實(shí)例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

引言

在之前的Qt項(xiàng)目中,我發(fā)現(xiàn)經(jīng)常會(huì)用到槽函數(shù)只需要執(zhí)行一次的情況。也就是說,槽函數(shù)執(zhí)行一次后,就需要disconnect對(duì)應(yīng)的連接。然而,真正操作起來實(shí)際上挺麻煩的,或者說不優(yōu)雅。

因?yàn)槟阈枰阎癱onnect時(shí)產(chǎn)生的QMetaObject::Connection對(duì)象保存起來,而保存它不能用局部變量,通常需要保存到類的成員變量中,或者其他生命周期足夠長的地方,以防止在disconnect它的時(shí)候,它已經(jīng)失效了。

總之,需要使用者自己維護(hù),因而增加了使用者的負(fù)擔(dān)。

如果有一個(gè)方法能夠在槽函數(shù)執(zhí)行完成后自動(dòng)disconnect掉連接就好了。我在網(wǎng)上找了一段時(shí)間,卻沒有找到合適的解決方案,相關(guān)討論也比較少,可能這不是一個(gè)很常見的需求吧。不過還是在GitHub上找到了一個(gè)相關(guān)的庫:https://github.com/misje/once,但是看它的源碼,感覺比較復(fù)雜。

它針對(duì)QObject::connect函數(shù)的每種情況,寫了對(duì)應(yīng)的實(shí)現(xiàn),總感覺太復(fù)雜了,應(yīng)該存在一種更通用的方法。

最近在閱讀了《C++ Primer》模板相關(guān)的章節(jié)后,我突然想到也許用完美轉(zhuǎn)發(fā)相關(guān)的東西可以簡化實(shí)現(xiàn)。于是試著寫了一下,貌似真得可以,代碼如下:

ConnectionUtil.h:

#pragma once
#include <QObject>
#include <QMap>
namespace ConnectionUtil
{
    typedef QMetaObject::Connection Conn;
    struct ConnKey {};
    extern QMap<ConnKey*, QPair<Conn, Conn>> connMap;
    class ReceiverObj : public QObject
    {
        Q_OBJECT
    public:
        explicit ReceiverObj(ConnKey *connKey) : key(connKey) {}
    public slots:
        void slot();
    private:
        ConnKey *key;
    };
    // 處理信號(hào)為SIGNAL(...)的情況
    template <typename Sender, typename ...Args>
    void connect(Sender &&sender, const char *signal, Args &&...args)
    {
        ConnKey *connKey = new ConnKey;
        Conn conn1 = QObject::connect(std::forward<Sender>(sender), signal, std::forward<Args>(args)...);
        Conn conn2 = QObject::connect(std::forward<Sender>(sender), signal, new ReceiverObj(connKey), SLOT(slot()));
        connMap.insert(connKey, qMakePair(std::move(conn1), std::move(conn2)));
    }
    // 處理其他情況
    template <typename Sender, typename Signal, typename ...Args>
    void connect(Sender &&sender, Signal &&signal, Args &&...args)
    {
        ConnKey *connKey = new ConnKey;
        Conn conn1 = QObject::connect(std::forward<Sender>(sender), std::forward<Signal>(signal), std::forward<Args>(args)...);
        Conn conn2 = QObject::connect(std::forward<Sender>(sender), std::forward<Signal>(signal), [connKey] { ReceiverObj(connKey).slot(); });
        connMap.insert(connKey, qMakePair(std::move(conn1), std::move(conn2)));
    }
}

ConnectionUtil.cpp:

#include "ConnectionUtil.h"
using namespace ConnectionUtil;
QMap<ConnKey *, QPair<Conn, Conn>> ConnectionUtil::connMap;
void ReceiverObj::slot()
{
    const QPair<Conn, Conn> &connections = connMap.value(key);
    QObject::disconnect(connections.first);
    QObject::disconnect(connections.second);
    connMap.remove(key);
    delete key;
    deleteLater();
}

這個(gè)實(shí)現(xiàn)假定QObject::connect的所有重載函數(shù)前兩個(gè)參數(shù)分別是Sender和Signal,事實(shí)上確實(shí)是這樣。關(guān)鍵點(diǎn)就是,額外建立一個(gè)連接,在收到信號(hào)后,disconnect用戶的連接。不過,我總感覺這個(gè)實(shí)現(xiàn)在多線程的情況下可能有bug,但在經(jīng)過簡單的測試后,暫時(shí)沒有發(fā)現(xiàn)。

使用示例如下:

ConnectionUtil::connect(this, SIGNAL(bong(int)), obj, SLOT(slotBong(int)), Qt::QueuedConnection);
ConnectionUtil::connect(this, &MainWindow::bong, obj, &SomeObject::slotBong, Qt::QueuedConnection);
ConnectionUtil::connect(this, &MainWindow::bong, this, []() {
    qDebug() << "bingo";
});

以上就是C++11 寫一個(gè)只觸發(fā)一次槽函數(shù)的Qt connect函數(shù)的詳細(xì)內(nèi)容,更多關(guān)于C++11 Qt connect函數(shù)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • VC++ 中ListCtrl經(jīng)驗(yàn)總結(jié)

    VC++ 中ListCtrl經(jīng)驗(yàn)總結(jié)

    這篇文章主要介紹了VC++ 中ListCtrl經(jīng)驗(yàn)總結(jié)的相關(guān)資料,需要的朋友可以參考下
    2015-06-06
  • C++ Qt開發(fā)之使用QHostInfo查詢主機(jī)地址

    C++ Qt開發(fā)之使用QHostInfo查詢主機(jī)地址

    Qt 是一個(gè)跨平臺(tái)C++圖形界面開發(fā)庫,利用Qt可以快速開發(fā)跨平臺(tái)窗體應(yīng)用程序,本文將重點(diǎn)介紹如何運(yùn)用QHostInfo組件實(shí)現(xiàn)對(duì)主機(jī)地址查詢功能,希望對(duì)大家有所幫助
    2024-03-03
  • C語言中的pause()函數(shù)和alarm()函數(shù)以及sleep()函數(shù)

    C語言中的pause()函數(shù)和alarm()函數(shù)以及sleep()函數(shù)

    這篇文章主要介紹了C語言中的pause()函數(shù)和alarm()函數(shù)以及sleep()函數(shù),是C語言入門學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下
    2015-09-09
  • C++如何將運(yùn)行結(jié)果保存到txt中

    C++如何將運(yùn)行結(jié)果保存到txt中

    這篇文章主要介紹了C++如何將運(yùn)行結(jié)果保存到txt中問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-08-08
  • 推箱子游戲C語言實(shí)現(xiàn)代碼

    推箱子游戲C語言實(shí)現(xiàn)代碼

    這篇文章主要為大家詳細(xì)介紹了推箱子游戲C語言實(shí)現(xiàn)代碼,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-12-12
  • C語言超詳細(xì)講解指針的概念與使用

    C語言超詳細(xì)講解指針的概念與使用

    本文主要講解C語言中指針和字符串的關(guān)系以及指針和數(shù)組的關(guān)系,在看本文之前大家可以先看看博主之前的C語言基礎(chǔ)篇,先對(duì)C語言指針先有個(gè)基礎(chǔ)的了解,有助于對(duì)本文章有更深一步的了解
    2022-05-05
  • C++實(shí)現(xiàn)String類的方法詳解

    C++實(shí)現(xiàn)String類的方法詳解

    在C語言中,沒有專門用來表示字符串的類型。雖然C語言為字符串提供了一系列的庫函數(shù),但這些函數(shù)與字符串這個(gè)類型是分開的。所以在C++中封裝了一個(gè)string類,來幫助我們操作字符串,本文就為大家提供了實(shí)現(xiàn)String類的方法,需要的可以參考一下
    2022-08-08
  • C++網(wǎng)絡(luò)編程詳細(xì)講解

    C++網(wǎng)絡(luò)編程詳細(xì)講解

    計(jì)算機(jī)是通過TCP/IP協(xié)議進(jìn)行互聯(lián)從而進(jìn)行通信的,為了把復(fù)雜的TCP/IP協(xié)議隱藏起來,更方便的實(shí)現(xiàn)計(jì)算機(jī)中兩個(gè)程序進(jìn)行通信,引出了socket這個(gè)概念
    2022-10-10
  • boost.asio框架系列之定時(shí)器Timer

    boost.asio框架系列之定時(shí)器Timer

    這篇文章介紹了boost.asio框架系列之定時(shí)器Timer,文中通過示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-06-06
  • boost.asio框架系列之socket編程

    boost.asio框架系列之socket編程

    這篇文章介紹了boost.asio框架系列之socket編程,文中通過示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-06-06

最新評(píng)論

都安| 汪清县| 九江县| 眉山市| 开封县| 柏乡县| 湘潭市| 潞西市| 洪泽县| 张北县| 新昌县| 兴化市| 河南省| 古蔺县| 航空| 百色市| 紫云| 安龙县| 舟曲县| 赞皇县| 磴口县| 冷水江市| 墨脱县| 台江县| 田东县| 巍山| 称多县| 防城港市| 郁南县| 绥芬河市| 千阳县| 阿巴嘎旗| 邯郸县| 清镇市| 徐闻县| 镇巴县| 丰原市| 十堰市| 运城市| 凌云县| 桃园市|