久久久久久久av_日韩在线中文_看一级毛片视频_日本精品二区_成人深夜福利视频_武道仙尊动漫在线观看

Qt 插槽和 C++11 lambda

Qt Slots and C++11 lambda(Qt 插槽和 C++11 lambda)
本文介紹了Qt 插槽和 C++11 lambda的處理方法,對大家解決問題具有一定的參考價值,需要的朋友們下面隨著小編來一起學習吧!

問題描述

我有一個 QAction 項,我初始化如下:

I have a QAction item that I initialize like follows:

QAction* action = foo->addAction(tr("Some Action"));
connect(action, SIGNAL(triggered()), this, SLOT(onSomeAction()));

然后 onSomeAction 看起來像:

And then onSomeAction looks something like:

void MyClass::onSomeAction()
{
    QAction* caller = qobject_cast<QAction*>(sender());
    Q_ASSERT(caller != nullptr);

    // do some stuff with caller
}

這很好用,我取回了 caller 對象,并且可以按預期使用它.然后我嘗試使用 C++11 的方式來連接對象,如下所示:

This works fine, I get the caller object back and I'm able to use it as expected. Then I try the C++11 way to connect the object like such:

connect(action, &QAction::triggered, [this]()
{
    QAction* caller = qobject_cast<QAction*>(sender());
    Q_ASSERT(caller != nullptr);

    // do some stuff with caller
});

但是 caller 始終為 null,因此 Q_ASSERT 會觸發.如何使用 lambdas 來獲取發件人?

But caller is always null and thus the Q_ASSERT triggers. How can I use lambdas to get the sender?

推薦答案

簡單的答案是:你不能.或者,更確切地說,您不想(或不需要!)使用 sender().只需捕獲并使用 action.

The simple answer is: you can't. Or, rather, you don't want (or need!) to use sender(). Simply capture and use action.

//                                Important!
//                                   vvvv
connect(action, &QAction::triggered, this, [action, this]() {
    // use action as you wish
    ...
});

this 作為函子的對象上下文的規范確保函子不會被調用,如果動作或 this(一個 QObject) 不復存在.否則,函子會嘗試引用懸空指針.

The specification of this as the object context for the functor ensures that the functor will not get invoked if either the action or this (a QObject) cease to exist. Otherwise, the functor would try to reference dangling pointers.

通常,在為傳遞給 connect 的函子捕獲上下文變量時,必須滿足以下條件,以避免使用懸空指針/引用:

In general, the following must hold when capturing context variables for a functor passed to connect, in order to avoid the use of dangling pointers/references:

  1. connect 的源和目標對象的指針可以通過值來捕獲,如上.保證如果調用函子,連接的兩端都存在.

  1. The pointers to the source and target objects of connect can be captured by value, as above. It is guaranteed that if the functor is invoked, both ends of the connection exist.

connect(a, &A::foo, b, [a, b]{});

ab 在不同線程中的情況需要特別注意.不能保證一旦進入函子,某個線程就不會刪除任何一個對象.

Scenarios where a and b are in different threads require special attention. It can not be guaranteed that once the functor is entered, some thread will not delete either object.

一個對象只在它的thread()中被破壞,或者在任何線程中,如果thread() == nullptr,這是慣用的.由于線程的事件循環調用函子,因此對于 b 而言,空線程永遠不會成為問題——沒有線程,函子將不會被調用.唉,b 的線程中 a 的生命周期無法保證.因此,通過值捕獲操作的必要狀態會更安全,這樣 a 的生命周期就不是問題.

It is idiomatic that an object is only destructed in its thread(), or in any thread if thread() == nullptr. Since a thread's event loop invokes the functor, the null thread is never a problem for b - without a thread the functor won't be invoked. Alas, there's no guarantee about the lifetime of a in b's thread. It is thus safer to capture the necessary state of the action by value instead, so that a's lifetime is not a concern.

// SAFE
auto aName = a->objectName();       
connect(a, &A::foo, b, [aName, b]{ qDebug() << aName; });
// UNSAFE
connect(a, &A::foo, b, [a,b]{ qDebug() << a->objectName(); });

  • 如果您絕對確定指向其他對象的對象的生命周期與連接的生命周期重疊,則可以通過值捕獲指向其他對象的原始指針.

  • Raw pointers to other objects can be captured by value if you're absolutely sure that the lifetime of the objects they point to overlaps the lifetime of the connection.

    static C c;
    auto p = &c;
    connect(..., [p]{});
    

  • 對象引用同上:

  • Ditto for references to objects:

    static D d;
    connect(..., [&d]{});
    

  • 非從 QObject 派生的不可復制對象應通過它們的共享指針按值捕獲.

  • Non-copyable objects that don't derive from QObject should be captured through their shared pointers by value.

    std::shared_ptr<E> e { new E };
    QSharedPointer<F> f { new F; }
    connect(..., [e,f]{});
    

  • QObject可以被QPointer捕獲;在函數中使用之前必須檢查它的值.

  • QObjects living in the same thread can be captured by a QPointer; its value must be checked prior to use in the functor.

    QPointer<QObject> g { this->parent(); }
    connect(..., [g]{ if (g) ... });
    

  • QObject存在于其他線程中,必須被共享指針或弱指針捕獲.他們的父級必須在銷毀之前取消設置,否則您將進行雙重刪除:

  • QObjects living in other threads must be captured by a shared pointer or a weak pointer. Their parent must be unset prior to their destruction, otherwise you'll have double deletes:

    class I : public QObject {
      ...
      ~I() { setParent(nullptr); }
    };
    
    std::shared_ptr<I> i { new I };
    connect(..., [i]{ ... });
    
    std::weak_ptr<I> j { i };
    connect(..., [j]{ 
      auto jp = j.lock();
      if (jp) { ... }
    });
    

  • 這篇關于Qt 插槽和 C++11 lambda的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!

    【網站聲明】本站部分內容來源于互聯網,旨在幫助大家更快的解決問題,如果有圖片或者內容侵犯了您的權益,請聯系我們刪除處理,感謝您的支持!

    相關文檔推薦

    How can I read and manipulate CSV file data in C++?(如何在 C++ 中讀取和操作 CSV 文件數據?)
    In C++ why can#39;t I write a for() loop like this: for( int i = 1, double i2 = 0; (在 C++ 中,為什么我不能像這樣編寫 for() 循環: for( int i = 1, double i2 = 0;)
    How does OpenMP handle nested loops?(OpenMP 如何處理嵌套循環?)
    Reusing thread in loop c++(在循環 C++ 中重用線程)
    Precise thread sleep needed. Max 1ms error(需要精確的線程睡眠.最大 1ms 誤差)
    Is there ever a need for a quot;do {...} while ( )quot; loop?(是否需要“do {...} while ()?環形?)
    主站蜘蛛池模板: 亚洲国产成人精品久久久国产成人一区 | 久久精品国产久精国产 | 欧美一区二区小视频 | 国产日韩一区二区三免费 | 久久久久久色 | 亚洲精品一区国产精品 | 国产成人短视频在线观看 | 欧美精品一区二区三区在线四季 | 国产精品久久国产精品99 | 色偷偷噜噜噜亚洲男人 | 91在线影院| 日本在线观看视频 | 一区二区三区视频在线 | 亚洲视频一区在线观看 | 中文字幕一区二区三区不卡 | 国产精品久久777777 | 国产在线一区二区三区 | 久久美女视频 | 欧美一区二区三区在线视频 | 蜜桃综合在线 | 日韩免费看视频 | 国产成人精品免费 | 国产成人一区 | 欧美日韩亚洲三区 | 激情五月综合 | 欧洲免费毛片 | 午夜爽爽爽男女免费观看 | 一级网站| 中文字幕第一页在线 | 91在线视频网址 | 久久久精品网站 | 亚洲一区二区在线 | 国产精品精品视频一区二区三区 | 伊色综合久久之综合久久 | 青青操91| 三级在线视频 | 日韩一级免费观看 | 免费一区二区 | 五月婷婷导航 | 中文字幕国产 | 欧美成人激情视频 |