我正在开发一个使用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