我正在開發一個使用Qt的科學數據採集應用程序。由於我不是Qt的深度專家,因此我希望有一些體系結構在下列問題上提出建議:Qt SIGNAL的體系結構,具有子類特定的模板參數類型
該應用程序支持多個硬件採集接口,但我希望在這些接口之上提供一個通用API接口。每個接口都有一個樣本數據類型和一個數據單位。因此,我將每個設備的樣本矢量表示爲Boost.Units數量的std::vector
(即std::vector<boost::units::quantity<unit,sample_type> >
)。我想使用多播風格架構,每個數據源都將新收到的數據廣播給一個或多個感興趣的用戶。 Qt的Signal/Slot機制非常適合這種風格。所以,我希望每個數據源發出一個信號,如
typedef std::vector<boost::units::quantity<unit,sample_type> > SampleVector
signals:
void samplesAcquired(SampleVector sampleVector);
適用於該設備的單位和sample_type。由於元對象編譯器不支持temparted QObject
子類,因此似乎沒有辦法爲定義samplesAcquired
Signal的所有數據源設置(tempalted)基類。換句話說,以下不會工作:
template<T,U> //sample type and units
class DataSource : public QObject {
Q_OBJECT
...
public:
typedef std::vector<boost::units::quantity<U,T> > SampleVector
signals:
void samplesAcquired(SampleVector sampleVector);
};
我已經能夠拿出最好的選擇是兩個層次的方法:
template<T,U> //sample type and units
class IAcquiredSamples {
public:
typedef std::vector<boost::units::quantity<U,T> > SampleVector
virtual shared_ptr<SampleVector> acquiredData(TimeStamp ts, unsigned long nsamples);
};
class DataSource : public QObject {
...
signals:
void samplesAcquired(TimeStamp ts, unsigned long nsamples);
};
的samplesAcquired
信號現在爲收購提供了時間戳和樣本數量,客戶必須使用IAcquiredSamples
API來檢索這些樣本。顯然數據源必須繼承DataSource和IAcquiredSamples
。
這種方法的缺點似乎是在API簡單性方面的損失......如果客戶端可以在連接的插槽中獲得採集的樣本,那將會更好。能夠使用Qt的排隊連接也會使線程問題更容易,而不必在每個子類中的acquiredData
方法中管理它們。
另一種可能性是使用QVariant
參數。這必然使子類上的責任將其特定的樣本向量類型註冊爲Q_REGISTER_METATYPE
/qRegisterMetaType
。沒有什麼大不了的。但是,基類的客戶端將無法知道值類型是什麼類型,除非標記結構也與信號一起傳遞。我認爲這個解決方案至少與上面的解決方案一樣複雜,因爲它迫使抽象基類API的客戶端處理類型系統的一些更粗糙的方面。
那麼,有沒有辦法實現模板化信號參數?有沒有比我建議的更好的建築?
我認爲它可以更容易理解,如果你給這個std :: vector的Boost.Units數量的使用僞代碼 它需要運行時多態嗎? – user204724 2010-03-18 13:13:07
我不認爲有比你現有的兩個更好的解決方案。您是否考慮過使用模板參數可以使用的Boost Signals或Signals2? – baysmith 2010-03-27 02:56:21