亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

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

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

引言

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

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

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

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

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

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

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用戶(hù)的連接。不過(guò),我總感覺(jué)這個(gè)實(shí)現(xiàn)在多線程的情況下可能有bug,但在經(jīng)過(guò)簡(jiǎn)單的測(cè)試后,暫時(shí)沒(méi)有發(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 寫(xiě)一個(gè)只觸發(fā)一次槽函數(shù)的Qt connect函數(shù)的詳細(xì)內(nèi)容,更多關(guān)于C++11 Qt connect函數(shù)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • C++的STL中accumulate函數(shù)的使用方法

    C++的STL中accumulate函數(shù)的使用方法

    這篇文章主要介紹了C++的STL中accumulate的使用方法,accumulate作用是累加求和即自定義類(lèi)型數(shù)據(jù)處理,下文具體的操作方法需要的小伙伴可以參考一下
    2022-03-03
  • C++中cout的格式使用詳細(xì)介紹

    C++中cout的格式使用詳細(xì)介紹

    cout 是C++中 ostream 類(lèi)型的對(duì)象,該類(lèi)被封裝在 < iostream > 庫(kù)中,該庫(kù)定義的名字都在命名空間 std 中,所以 cout 全稱(chēng)是 std::cout 。本文重點(diǎn)給大家介紹C++中cout的格式使用,需要的朋友參考下吧
    2021-06-06
  • Qt自定義控件實(shí)現(xiàn)多彩色儀表盤(pán)

    Qt自定義控件實(shí)現(xiàn)多彩色儀表盤(pán)

    這篇文章主要為大家詳細(xì)介紹了Qt自定義控件實(shí)現(xiàn)多彩色儀表盤(pán),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-12-12
  • C語(yǔ)言判斷大小端的兩種方法

    C語(yǔ)言判斷大小端的兩種方法

    大小端的問(wèn)題在很多面試筆試中都會(huì)遇到,本文主要介紹了C語(yǔ)言判斷大小端的兩種方法,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2024-02-02
  • C語(yǔ)言多組輸入使用方法

    C語(yǔ)言多組輸入使用方法

    這篇文章主要給大家介紹了關(guān)于C語(yǔ)言多組輸入使用的相關(guān)資料,在 C語(yǔ)言中可以使用循環(huán)語(yǔ)句來(lái)實(shí)現(xiàn)多組輸入,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-07-07
  • 排列和組合算法的實(shí)現(xiàn)方法_C語(yǔ)言經(jīng)典案例

    排列和組合算法的實(shí)現(xiàn)方法_C語(yǔ)言經(jīng)典案例

    下面小編就為大家?guī)?lái)一篇排列和組合算法的實(shí)現(xiàn)方法_C語(yǔ)言經(jīng)典案例。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2016-09-09
  • 淺析C語(yǔ)言中strtol()函數(shù)與strtoul()函數(shù)的用法

    淺析C語(yǔ)言中strtol()函數(shù)與strtoul()函數(shù)的用法

    這篇文章主要介紹了淺析C語(yǔ)言中strtol()函數(shù)與strtoul()函數(shù)的用法,注意其將字符串轉(zhuǎn)換成long型的區(qū)別,需要的朋友可以參考下
    2015-08-08
  • C++用兩個(gè)棧實(shí)現(xiàn)一個(gè)隊(duì)列(面試官的小結(jié))

    C++用兩個(gè)棧實(shí)現(xiàn)一個(gè)隊(duì)列(面試官的小結(jié))

    這篇文章主要給大家介紹了關(guān)于C++用兩個(gè)棧實(shí)現(xiàn)一個(gè)隊(duì)列的相關(guān)資料,這是來(lái)自一名面試官的小結(jié),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用C++具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-05-05
  • C++ 數(shù)據(jù)結(jié)構(gòu)完全二叉樹(shù)的判斷

    C++ 數(shù)據(jù)結(jié)構(gòu)完全二叉樹(shù)的判斷

    這篇文章主要介紹了C++ 數(shù)據(jù)結(jié)構(gòu)完全二叉樹(shù)的判斷的相關(guān)資料,需要的朋友可以參考下
    2017-06-06
  • C++中的友元函數(shù)與友元類(lèi)詳情

    C++中的友元函數(shù)與友元類(lèi)詳情

    這篇文章主要介紹了C++中的友元函數(shù)與友元類(lèi)詳情,對(duì)類(lèi)的封裝是C++三大特性中的一個(gè)重要特性,封裝好的數(shù)據(jù)在類(lèi)的外部是訪問(wèn)不到的但是一旦出了問(wèn)題,想要操作被封裝的數(shù)據(jù)怎么辦呢?由此友元函數(shù)友元類(lèi)誕生了,下文我們來(lái)詳細(xì)來(lái)接一下具體的有緣類(lèi)吧
    2022-02-02

最新評(píng)論