简体   繁体   中英

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 .

I believe you need to inherit from QObject to emit Qt Signals. So I'd need to inherit from QObject for my 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.

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?

有一个非常重要的技术原因: 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

there are other classes which mirror this use such as QImage

Reason is simple containers are like values, you have assign operator, you can copy them clone and so on.

QObject s can't have such functionality, they are not copyable. 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.

It is certainly not true that you need to be a QObject to emit signals. All you need is there to be a QObject somewhere that emits the signals for you. 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. 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 . 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.

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. 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. 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. 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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