我想在QObservableCollection
周围创建一个QList
包装器(使用内部QList
实现并转发所有调用,同时为更改集合的函数发出某种CollectionsChanged信号) ,但我发现QList
不会继承QObject
。
我相信您需要从QObject
继承以发出Qt信号。所以我需要从QObject
继承我的QObeservableCollection。
但是QList
和QVector
以及其他Qt集合并没有从QObject
继承,所以我认为它们必须是某种收集的下行或问题。
我看到QSignalSpy继承了QObject
和QList<QList<QVariant>>
,所以他们可能没有看到继承QObject的理由?
答案 0 :(得分:5)
有一个非常重要的技术原因:moc
无法处理模板,这对于通用容器类型来说几乎是必需的。
答案 1 :(得分:4)
QList是一个值类型(如std::vector
),它使用隐式共享,而QObjects必须用作指针并禁止复制
还有其他类可以反映这种用法,例如QImage
答案 2 :(得分:3)
原因是简单的容器就像值,你有assign operator,你可以复制它们克隆等等。
QObject
s不能具有此功能,它们不可复制。试着想象一下当您创建具有连接的插槽和信号的对象的克隆时应该发生什么。这会导致一团糟。克隆对象的孩子应该怎么办?还应克隆?
另一件事是模板使用。作为QObject
的类模板是moc工具的真正问题。
答案 3 :(得分:3)
你需要成为QObject
发射信号肯定不是真的。您所需要的只是QObject
某个地方为您发出信号。如果您希望您的班级可以直接传递给QObject::connect
,那么您的班级应该向QObject*
提供转换运算符,该运算符返回指向此类代理对象的指针。这完全避开了整个没有模板的蠢蠢欲动。
class FrobinatorObject : public QObject {
Q_OBJECT
Q_SIGNAL void frobSignal();
...
};
template <typename T> class Frobinator {
QScopedPointer<FrobinatorObject> m_proxy;
// Could be a QSharedPointer, depending on what semantics we want
...
public:
operator FrobinatorObject*() const { return m_proxy.data(); }
};
...
Frobinator<int> frob;
QObject::connect(frob, SIGNAL(frobSignal()), ...);
// or
QObject::connect(frob, &FrobinatorObject::frobSignal, ...);
另请注意,虽然模板参数化类中不能包含信号或插槽,但您可以将它们放在基类中,然后从中派生出来。基类可以处理类型删除的参数。所以:
// This won't work
template <typename T> class TemplateClass : public QObject {
Q_OBJECT
Q_SLOT void aSlot(const T *);
...
};
// But this certainly does work
class BaseClass : public QObject {
Q_OBJECT
Q_SLOT void aSlot(const void *);
...
}
template <typename T> class TemplateClass : public BaseClass {
void aMethod(const T * t) {
BaseClass::aSlot((const void*)&t);
}
...
}
TemplateClass
还可以动态地将正确类型签名的插槽添加到BaseClass
。虽然这需要对Qt的内部结构有所了解,但对于一个应该是可重用的框架式类的类来说,它当然可以完成。
答案 4 :(得分:2)
虽然我无法深入了解开发人员的想法,但我会说没有必要。 QList是一个简单的容器。它应该包含元素,允许它们的添加或删除,迭代它们等等。
不需要父母或子女。对信号或插槽没有立即需求。这是保持简单的问题。
如果确实需要QList提供的其他功能,那么实施起来就很容易了。但就一般情况而言,我认为不要过度复杂化是一个合理而合乎逻辑的决定。
答案 5 :(得分:1)
对于大多数用途而言,继承QObject的额外开销是不必要的。容器应尽可能小而且快。
如果你想从QList继承并为你自己的类提供该功能,你可以这样做。