QT 信號槽connect寫法函數
先看下示例:this
QPushButton *btn = new QPushButton; // 方式一:老式寫法 connect(btn, SIGNAL(clicked()), this, SLOT(close())); // 方式二:Qt5後新寫法 connect(btn, &QPushButton::clicked, this, &MainWindow::close); // 方式三:lambda表達式 connect(btn, &QPushButton::clicked, this, [&]() { this->close(); });
方式一 老式寫法,在編譯的時候即便信號或槽不存在也不會報錯,可是在執行的時候無效,對於C++這種靜態語言來講,這是不友好的,不利於調試;指針
方式二 Qt5後推薦的寫法,若是編譯的時候信號或槽不存在是沒法編譯經過的,至關於編譯時檢查,不容易出錯,還有就是槽的寫法能夠直接寫在public控制域下,不必定非要寫在public slots:控制域下;調試
方式三 採用了lambda表達式的寫法,更加方便快捷。code
關於lambda須要注意一點:生命週期
QTimer::singleShot(3000, /* this, */ [&]{ this->close(); }); connect(btn, &QPushButton::clicked, /* this, */ [&]() { this->close(); });
看下上面的示例,當咱們用lambda表達式的時候,槽的接收者QObject是能夠省略不寫的,這時候Qt會默認發射者與接收者屬於同一個QObject;io
//connect to a functor template <typename Func1, typename Func2> static inline typename std::enable_if<QtPrivate::FunctionPointer<Func2>::ArgumentCount == -1, QMetaObject::Connection>::type connect(const typename QtPrivate::FunctionPointer<Func1>::Object *sender, Func1 signal, Func2 slot) { return connect(sender, signal, sender, slot, Qt::DirectConnection); }
當咱們省略槽函數接收者QObject時,那咱們就必需要注意lambda內成員的生命週期;例如示例的singleShot,若在槽函數響應前,this已經銷燬變爲無效指針,後果就會很嚴重!!!編譯
爲何?class
咱們知道,connect的發射者與接收者任意一個銷燬,那麼這個connect就已經斷開了;當咱們省略接收者QObject的時候,發射者與接收者屬於同一個QObject;在上面的示例中,信號槽connect關聯依然存在,信號槽依然會觸發,但此時this已經被銷燬cli