![](/img/trans.png)
[英]QList children - struct or custom classes derived from QObject?
[英]Why is a QList not derived from a QObject?
我想在QList
周围创建一个QObservableCollection
包装器(使用内部QList
实现并转发所有调用,同时为更改集合的函数发出某种CollectionsChanged信号),但我看到QList
不从QObject
继承。
我相信你需要从QObject
继承以发出Qt信号。 所以我需要从QObject
继承我的QObeservableCollection。
但是QList
和QVector
以及其他Qt集合并没有从QObject
继承,所以我想他们必须在制作集合时遇到某种缺点或问题。
我看到QSignalSpy继承了QObject
和QList<QList<QVariant>>
所以也许他们只是没有看到从QObject继承的理由?
有一个非常重要的技术原因: moc
无法处理模板,这对于通用容器类型来说几乎是必需的。
QList是一个值类型(如std::vector
),它使用隐式共享,而QObjects必须用作指针并禁止复制
还有其他类可以反映这种用法,例如QImage
原因是简单的容器就像值,你有assign operator,你可以复制它们克隆等等。
QObject
不能具有这样的功能,它们不可复制。 试着想象一下当您创建具有连接的插槽和信号的对象的克隆时应该发生什么。 这会导致一团糟。 克隆对象的孩子应该怎么办? 还应该克隆?
另一件事是模板使用。 作为QObject
类模板是moc工具的真正问题。
你需要成为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的内部结构有所了解,但对于一个应该是可重用的框架式类的类当然可以做到。
虽然我无法深入了解开发人员的想法,但我会说没有必要。 QList是一个简单的容器。 它应该包含元素,允许它们的添加或删除,迭代它们等。
它不需要父母或孩子。 对信号或插槽没有立即需求。 这是保持简单的问题。
如果确实需要QList提供的其他功能,那么实现起来就很容易了。 但就一般情况而言,我认为不要过度复杂化是一个合理而合乎逻辑的决定。
继承自QObject的额外开销对于大多数用途来说是不必要的。 容器应尽可能小和尽快。
如果您想继承QList并为自己的类提供该功能,那么您可以这样做。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.