Qt的特點就是提供了Signal/Slot機制來提供一個thread-safe的物件溝通功能。
GUI的事件連結通常是用call back機制,也就是元件本身提供可監聽的事件類型,由使用者提供若干函式註冊給這些事件,讓事件發生時會自動喚起使用者自訂函式。JavaScript使用的DOM便是典型例子。
而Signal/Slot的運作方式則是讓使用者在元件上自訂signal[?]和slot[?]。使用者可以在任何執行點上發射signal,而slot則可以和參數相同的任意signal連結。
GUI的事件連結通常是用call back機制,也就是元件本身提供可監聽的事件類型,由使用者提供若干函式註冊給這些事件,讓事件發生時會自動喚起使用者自訂函式。JavaScript使用的DOM便是典型例子。
而Signal/Slot的運作方式則是讓使用者在元件上自訂signal[?]和slot[?]。使用者可以在任何執行點上發射signal,而slot則可以和參數相同的任意signal連結。
Qt這麼設計的好處在於它很靈活,事件觸發的種類不再受限於事件模型;在任何執行點上皆可發射signal,也就是說也可以在slot裡再發射另一個signal,甚至於連結時也不只能夠在signal和slot間綁定,還可以使用在signal和signal之間,多對多的連結就更不在話下。
像這種明顯就超出了C++語言範圍的功能,其實作方式就帶來了一些缺點。這個機制大量地依賴一種Meta-Programming的技術,Qt稱之為Meta-Object System;自訂signal/slot時,需要使用moc這個Qt內附的外部工具,先parse類別的宣告,把signal和slot轉成字串,額外定義signal和meta-object處理的code,存成另一個原始檔,再和原本寫好的原始檔連結再一起,才能正常連結。
好了,我想各位看倌看出一個問題點了:moc要求類別的宣告和定義要分開,但是C++能支援分散template編譯的compiler少之又少。這是第一個問題。
另一個問題是,meta-object底層的實作方式是把類別和方法的名稱轉成字串,然後再做一些有點骯髒的處理,這很明顯地和template的具現化方式互相衝突。
好了,我想各位看倌看出一個問題點了:moc要求類別的宣告和定義要分開,但是C++能支援分散template編譯的compiler少之又少。這是第一個問題。
另一個問題是,meta-object底層的實作方式是把類別和方法的名稱轉成字串,然後再做一些有點骯髒的處理,這很明顯地和template的具現化方式互相衝突。
因此如果想在template class上使用signal/slot機制的話,必須要先在non-template class宣告signal/slot,再宣告一個template class去繼承它。不過如果連signal/slot的參數都要模版化,要作的手術會更複雜些。
沒有留言:
張貼留言