3.1K
聚合
聚合由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
这里也许看不到使用聚合的好处,但是在后面我们涉及到真正的插件实现的时候,我们就会看到这样做的优势了。