简体   繁体   English

为什么QList不是从QObject派生的?

[英]Why is a QList not derived from a QObject?

I wanted to create a QObservableCollection wrapper around a QList (using an internal QList for implementation and forwarding all calls while emiting some sort of CollectionsChanged signal for functions that change the collection), but I see that QList does not inherit from QObject . 我想在QList周围创建一个QObservableCollection包装器(使用内部QList实现并转发所有调用,同时为更改集合的函数发出某种CollectionsChanged信号),但我看到QList不从QObject继承。

I believe you need to inherit from QObject to emit Qt Signals. 我相信你需要从QObject继承以发出Qt信号。 So I'd need to inherit from QObject for my QObeservableCollection. 所以我需要从QObject继承我的QObeservableCollection。

But QList and QVector and the other Qt collections doen't inherit from QObject , so I imagine their must be some sort of downside or problem making a collection. 但是QListQVector以及其他Qt集合并没有从QObject继承,所以我想他们必须在制作集合时遇到某种缺点或问题。

I see that QSignalSpy inherits from both QObject and QList<QList<QVariant>> so maybe they just didn't see a reason to inherit from QObject? 我看到QSignalSpy继承了QObjectQList<QList<QVariant>>所以也许他们只是没有看到从QObject继承的理由?

有一个非常重要的技术原因: moc无法处理模板,这对于通用容器类型来说几乎是必需的。

QList is meant to be a value type (like std::vector ) which uses implicit sharing while QObjects must be used as pointers and disallow copying QList是一个值类型(如std::vector ),它使用隐式共享,而QObjects必须用作指针并禁止复制

there are other classes which mirror this use such as QImage 还有其他类可以反映这种用法,例如QImage

Reason is simple containers are like values, you have assign operator, you can copy them clone and so on. 原因是简单的容器就像值,你有assign operator,你可以复制它们克隆等等。

QObject s can't have such functionality, they are not copyable. QObject不能具有这样的功能,它们不可复制。 Try imagine what should happen when you creating clone of object with connected slots and signals. 试着想象一下当您创建具有连接的插槽和信号的对象的克隆时应该发生什么。 It will lead to total mess. 这会导致一团糟。 And what should happen with children of cloned object? 克隆对象的孩子应该怎么办? Should be also cloned? 还应该克隆?

Another thing is templates usage. 另一件事是模板使用。 Class template which is a QObject is real problem for moc a tool. 作为QObject类模板是moc工具的真正问题。

It is certainly not true that you need to be a QObject to emit signals. 你需要成为QObject才能发出信号,这当然不是真的。 All you need is there to be a QObject somewhere that emits the signals for you. 你需要的就是在某处为你发出信号的QObject If you want your class to be directly passable to QObject::connect , your class should provide a conversion operator to QObject* that returns the pointer to such a proxy object. 如果您希望您的类可以直接传递给QObject::connect ,那么您的类应该为QObject*提供一个转换运算符,它返回指向这样一个代理对象的指针。 This completely sidesteps the whole no-templates-with-moc brouhaha. 这完全避开了整个无模板与摩洛哥的骚动。

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, ...);

Also note that while it's true that you can't have signals nor slots in a template-parametrized class, you can certainly have them in a base class that you then derive from. 另请注意,虽然模板参数化类中不能包含信号或插槽,但您可以将它们放在基类中,然后从中派生出来。 The base class can deal with type-deleted arguments. 基类可以处理类型删除的参数。 So: 所以:

// 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);
  }
  ...
}

The TemplateClass can also dynamically add slots of the correct type signature to the BaseClass . TemplateClass还可以动态地将正确类型签名的插槽添加到BaseClass While that requires some understanding of Qt's internals, it can certainly be done for a class that's supposed to be a reusable, framework-style class. 虽然这需要对Qt的内部结构有所了解,但对于一个应该是可重用的框架式类的类当然可以做到。

While I can't look into the minds of the developers, I would say that there's simply no need. 虽然我无法深入了解开发人员的想法,但我会说没有必要。 A QList is a simple container. QList是一个简单的容器。 It should hold elements, allow for their addition or removal, iteration over them, etc. 它应该包含元素,允许它们的添加或删除,迭代它们等。

It does not need a parent or children. 它不需要父母或孩子。 There's no immediate need for signals or slots. 对信号或插槽没有立即需求。 It's a matter of keeping things simple. 这是保持简单的问题。

If you do indeed require additional functionality beyond what a QList provides, it's easy enough to implement. 如果确实需要QList提供的其他功能,那么实现起来就很容易了。 But as for a general case, I guess it's a reasonable and logical decision to not overcomplicate things. 但就一般情况而言,我认为不要过度复杂化是一个合理而合乎逻辑的决定。

The extra overhead in inheriting from QObject is unnecessary for the majority of uses. 继承自QObject的额外开销对于大多数用途来说是不必要的。 Containers should be as small and as fast as possible. 容器应尽可能小和尽快。

If you wanted to inherit from QList and provide that functionality for a class of your own, you can do that. 如果您想继承QList并为自己的类提供该功能,那么您可以这样做。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM