最近在論壇上看到了這個方面的問題,詳見這裏。
隨後淺淺地學習了一會兒,看到了Qt官方論壇上給出的說明,以爲C++11的functional鏈接方法仍是比Qt4既有的宏鏈接方法有很大不一樣。
官方論壇的文檔:http://doc.qt.io/qt-5/signalsandslots-syntaxes.htmlcss
咱們在一個簡單的Dialog中,安排以下幾個信號與槽:html
class SSTest : public QDialog { //... signals: void sgn_test1(QByteArray arr); void sgn_test2(int n); void sgn_test2(QString s); void sgn_test3(double c, double d); public slots: void slt_1(); void slt_2(double v); void slt_2(QString s); void slt_3(int s); //... }; //cpp //...... void SSTest::slt_1() { qDebug()<<"SSTest::slt_1()"; } void SSTest::slt_2(double v) { qDebug()<<"SSTest::slt_2(double v):"<<v; } void SSTest::slt_2(QString s) { qDebug()<<"SSTest::slt_2(QString s):"<<s; } void SSTest::slt_3(int s) { qDebug()<<"SSTest::slt_3(int s):"<<s; }
然後,在構造函數中,直接採用文檔所述方法,進行鏈接.markdown
此類狀況,對應 sgn_test一、slt_1
直接鏈接便可:函數
connect (this,&SSTest::sgn_test1,this,&SSTest::slt_1); connect (this,&SSTest::sgn_test3,this,&SSTest::slt_3);
編譯OK,說明,槽的參數能夠比信號少。而且,存在着隱含參數轉換:
第一行,QByteArray arr 參數被忽略了,由於槽沒有參數。
第二行,double c, double d 兩個參數,第二個被忽略了,由於槽只有一個int參數。第一個參數被隱含轉換。
測試:學習
emit sgn_test1(QByteArray()); emit sgn_test3(1.7,2.2);
輸出:測試
SSTest::slt_1() SSTest::slt_3(int s): 1
可是,若是咱們把不支持隱含轉換的信號與槽鏈接,則會錯誤:this
connect (this,&SSTest::sgn_test1,this,&SSTest::slt_3);
QByteArray 沒法轉換爲 int, 所以沒法經過編譯(具體錯誤與編譯器相關):url
C:\...\qobjectdefs_impl.h:299: error: 'QByteArray::operator QNoImplicitBoolCast() const' is private within this context enum { value = sizeof(test(dummy())) == sizeof(int) }; ~~~~~^~~~~~~~~~
咱們試着簡單鏈接sgn_test3和slt_2spa
connect (this,&SSTest::sgn_test3,this,&SSTest::slt_2);
與估計的同樣,沒法編譯:.net
C:\...\sstest.cpp:15: error: no matching function for call to 'SSTest::connect(SSTest*, void (SSTest::*)(double, double), SSTest*, <unresolved overloaded function type>)' connect (this,&SSTest::sgn_test3,this,&SSTest::slt_2); ^
此時,咱們採用下面這兩種方式之一,便可:
connect (this,&SSTest::sgn_test3,this,static_cast<void(SSTest::*)(double)>(&SSTest::slt_2));
或者(C++14以上)
connect (this,&SSTest::sgn_test3,this,qOverload<double>(&SSTest::slt_2));
這等於強制指定了鏈接方法。測試:
emit sgn_test3(1.7,2.2);
輸出:
SSTest::slt_2(double v): 1.7
有了上面的經驗,面對重載已經不怕了:
//C++14風格同時指定信號、槽的參數表 connect (this,qOverload<QString>(&SSTest::sgn_test2),this,qOverload<QString>(&SSTest::slt_2)); //static_cast風格同時指定信號、槽的參數表 connect (this,static_cast<void(SSTest::*)(int)>(&SSTest::sgn_test2),this,static_cast<void(SSTest::*)(double)>(&SSTest::slt_2)); //信號重載,鏈接到單一的槽 connect (this,static_cast<void(SSTest::*)(int)>(&SSTest::sgn_test2),this,&SSTest::slt_1);
測試:
emit sgn_test2("haha!"); emit sgn_test2(1);
輸出:
SSTest::slt_2(QString s): "haha!" SSTest::slt_2(double v): 1 SSTest::slt_1()
固然,既然Qt5採用的是functional機制,必定能夠用lambda:
int p = 100;
connect (this,&SSTest::sgn_test3,[=](double a ,double b)->void{ qDebug()<<(p*a+b); });
測試:
emit sgn_test3(1.7,2.2);
輸出:
172.2
傳統的Qt4 Signal-Slot宏鏈接兼容性好,可是沒有編譯時檢查,每每會因爲筆誤,產生預料以外的效果。如今,有了C++11 functional的支持,能夠藉助編譯器進行嚴格的類型檢查,明顯是有利於調試了。
http://blog.csdn.net/goldenhawking/article/details/78766676