2.2K
聚合
聚合由Aggregation
命名空间提供。它为我们提供一种将不同类型的QObject
“粘合”在一起的能力,这样,你就可以将它们“相互转换”。使用这个命名空间中的类和函数,你就可以方便地管理相关对象。在聚合中管理的对象可以由该聚合“转换成”对象的类型。
传统实现方式
假设有一个对象实现了两个接口。那么,我们可以编写如下代码:
class Interface1 { .... }; Q_DECLARE_INTERFACE("Interface1", "Interface1"); class Interface2 { .... }; Q_DECLARE_INTERFACE("Interface2", "Interface2"); class Bundle : public QObject, public Interface1, public Interface2 { Q_OBJECT Q_INTERFACES(Interface1 Interface2) .... }; Bundle bundle;
现在,我们有一个对象bundle
,同时实现了Interface1
和Interface2
。我们可以使用转换运算符,将bundle
转换成Interface1
或者Interface2
:
Interface1* iface1Ptr = qobject_cast<Interface1*>(&bundle); Interface2* iface2Ptr = qobject_cast<Interface2*>(&bundle);
Qt Creator 实现方式
Qt Creator 的Aggregation
库提供了一种更加简洁的方式,来定义接口,然后将其打包成一个对象。创建Aggregation::Aggregate
实例,然后将对象添加进该对象。加入聚合的每一个对象都可以实现一个接口。下面的代码显示了如何创建聚合。
#include <aggregation/aggregate.h> class Interface1 : public QObject { Q_OBJECT public: Interface1() { } ~Interface1() { } }; class Interface2 : public QObject { Q_OBJECT public: Interface2() { } ~Interface2() { } }; Aggregation::Aggregate bundle; bundle.add(new Interface1); bundle.add(new Interface2);
聚合实例 bundle 现在有两个接口的实现。如果需要转换成相应接口,可以使用如下代码:
Interface1* iface1Ptr = Aggregation::query<Interface1>(&bundle); Interface2* iface2Ptr = Aggregation::query<Interface2>(&bundle);
利用聚合,你可以多次添加同一接口。例如:
Aggregation::Aggregate bundle; bundle.add(new Interface1); bundle.add(new Interface2); bundle.add(new Interface1); bundle.add(new Interface1); QList<Interface1*^gt; iface1Ptrs = Aggregation::query_all<Interface1>(&bundle);
使用Aggregation
的另一优点是,delete 聚合中的任一对象,都可以将整个聚合 delete 掉。例如:
Aggregation::Aggregate* bundle = new Aggregation::Aggregate; bundle->add(new Interface1); bundle->add(new Interface2); Interface1* iface1Ptr = Aggregation::query(bundle); delete iface1Ptr; // 同时会 delete 这个 bundle 及其中所有对象 // 等价于 delete bundle
这里也许看不到使用聚合的好处,但是在后面我们涉及到真正的插件实现的时候,我们就会看到这样做的优势了。