Qt 5 中的訊號槽

發表於2017-01-07

Qt4中的訊號槽

Qt4中的訊號槽是通過SIGNAL,SLOT兩個巨集,將引數轉換成字串.Qt編譯前,會從原始碼的標頭檔案中提取由signalslot宣告的訊號和槽的函式,
將其組成一張訊號和槽對應的字串表.connect函式的作用是,將訊號關聯的槽字串,同這張表的資訊進行對比.這樣訊號發出的時候,就可以知道呼叫哪一個槽函式了.

Qt4訊號槽的不足

  1. 沒有編譯期的檢查:Qt4中的訊號槽會被巨集轉化成字串處理,而字串的比較機制是在程式執行的時候檢測的.而且,轉換成字串後,訊號槽的引數資料型別就會丟失.這就導致,有的時候,訊號槽在編譯的時候沒有問題,在執行的時候,反而出錯.
  2. 無法使用相容型別的引數:因為訊號槽的機制使用的是字串的匹配的方法,所以,槽函式的引數型別的名字,必須和訊號引數型別的名字一致,同時,還必須和標頭檔案中宣告的型別名字一致,也就是字串意義上的嚴格相同.如果使用了typdef或者namespace這樣的型別,雖然實際的型別是一樣的,但是由於字串的名字不一樣,所以Qt4中是會有錯誤的.如下虛擬碼示例(實際型別都是int,但因為按照字串處理,所以Qt4中,編譯前不能通

Qt5中的訊號槽

Qt5中不僅解決了上述Qt4中的問題,而且還有一些擴充.

  1. 支援編譯期的檢查:拼寫錯誤,槽函式引數個數大於訊號引數的個數等;
  2. 支援相容型別的自動轉換;
  3. 槽允許連線到任意的函式:Qt5中,因為槽使用的是函式指標,所以槽的呼叫,可以是任意的成員函式,靜態函式,還可以是C++11 的lambda表示式;Qt4中槽的宣告一般是private slots,private是私有限制,只有把槽函式當作普通函式使用的時候,才會體現私有的性質.而SLOT,把槽函式轉化成了字串,此時private是不起作用的.Qt5中,因為使用的是函式指標,所以在類的外部,connect是無法關聯一個類的私有槽的,否則,編譯的時候就會報錯.

總之,Qt5中,增加了訊號槽的靈活性,加強了訊號槽的檢測性.

Qt5訊號槽的語法例子

常用用法

訊號槽的過載

解決方法:

  • 使用Qt4的方法(不再介紹)
  • Qt5顯示轉換函式指標

帶預設數值的槽函式

解決方法:

  • 進一步的封裝函式(不做介紹)
  • 採用Qt5的C++11 lambda表示式(表示式規則暫且不做詳細介紹)

[update:2016_11_20]

思考this的省略?

前面提到過connect函式的第三個引數this指標是可以省略的.但是在某些情況下this是絕不可以省略的.甚至我建議大家為了避免不必要的錯誤, this指標最好不要省略, 還是帶上比較好.connect函式基本是如下的原型:

所以,一定要明確的區分每個引數的具體意義, 馬馬虎虎最終還是自己填坑.

你也看到connect是可以使用C++的匿名函式的, 也是可以省略this的,但是, 這一步一定要小心了. 尤其是當你在使用執行緒的時候, 在接收執行緒訊號的時候, 一萬個小心.比如:

參考

《Qt 5程式設計入門》

相關文章