先看下示例:
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表達式的寫法,更加方便快捷。
關于lambda需要注意一點:
QTimer::singleShot(3000, /* this, */ [&]{this->close();});connect(btn, &QPushButton::clicked, /* this, */ [&]() {this->close();});
看下上面的示例,當我們用lambda表達式的時候,槽的接收者QObject是可以省略不寫的,這時候Qt會默認發射者與接收者屬于同一個QObject;
//connect to a functortemplate <typename Func1, typename Func2>static inline typename std::enable_if<QtPrivate::FunctionPointer<Func2>::ArgumentCount == -1, QMetaObject::Connection>::typeconnect(const typename QtPrivate::FunctionPointer<Func1>::Object *sender, Func1 signal, Func2 slot){return connect(sender, signal, sender, slot, Qt::DirectConnection);}
當我們省略槽函數接收者QObject時,那我們就必須要注意lambda內成員的生命周期;
例如示例的singleShot,若在槽函數響應前,this已經銷毀變為無效指針,后果就會很嚴重!!!
為什么?
我們知道,connect的發射者與接收者任意一個銷毀,那么這個connect就已經斷開了;
當我們省略接收者QObject的時候,發射者與接收者屬于同一個QObject;
在上面的示例中,信號槽connect關聯依然存在,信號槽依然會觸發,但此時this已經被銷毀就不好玩了!
另外:
?使用lamda表達式的話就不能用SIGNAL函數,不然會報錯
connect(timerChart, &QTimer::timeout, this,[&]{timer_count+=0.2;});
SIGNAL函數和SLOT函數要一起用
?