How to cast interfaces to QObjects?
-
I'd like to know if there is any way to use interfaces with Qt in a way that lets me handle objects by their interface type rather than their base type.
For example, say I have a Performer class that I use to define the behavior of some other classes that inherit QObject:
class Performer { virtual ~Performer() {} virtual QString name() = 0; virtual void doAct() = 0; } class Clown : public QObject, public Performer { QString name() override { return "Binky"; } virtual void doAct() override { /* */ } } class LionTamer : public QObject, public Performer { QString name() override { return "Leonardo"; } virtual void doAct() override { /* */ } } class BigTop : public QWidget { Q_OBJECT QList<QPointer<Performer>> performers; void addPerformer(QPointer<Performer> p) { performers.add(p); } void updatePerformers() { for (QPointer<Performer> p: performers) { if (!p.isNull()) { Performer* per = p.data(); qDebug(per.name()); } } } }
How should BigTop maintain a list of Performers? Just using the Performer class gives me compile errors about an invalid static cast from QObject* to Performer*. Is there a way to make the compiler aware of the Qt-ness of the interface?
I did find the Q_DECLARE_INTERFACE, but as far as I can tell that seems to be more for declaring plugins than for using for this sort of casting.
-
@kitfox said in How to cast interfaces to QObjects?:
I did find the Q_DECLARE_INTERFACE, but as far as I can tell that seems to be more for declaring plugins than for using for this sort of casting.
it is actually used to tell the meta system about the type. Which also lets you use qobject_cast also on interfaces than rather only on QObjects.
-
You need to use Q_OBJECT macto too. Otherwise, qobject_cast<> will fails.
-
Have you used both Q_DECLARE_INTERFACE for the type, and Q_INTERFACES in the classes that inherit the interface?
Please show your code for that, and the line with the qobject_cast -
I did have a Q_OBJECT declared, but forgot to include it in my sample code. I've edited the example to include it.
I had forgotten to also declare Q_INTERFACES after my Q_OBJECT, but adding these in did not solve the problem.
The cast happens implicitly when a QPointer is dereferenced. I've edited the example code to be a bit more explicit. The below is the code in qpointer.h that is called in response to p.data():
inline T* data() const { return static_cast<T*>( wp.data()); }
-
You can't use anything with
QPointer
, it has to be specifically aQObject
.Which brings me to my second point, I don't really see a reason for you to use
QPointer
at all, this is not a catch-all memory management, it's for holding references to objects you don't own.Thirdly, if your all derived classes are going to be
QObject
s, then just make the base class aQObject
. -
@kshegunov said in How to cast interfaces to QObjects?:
I don't really see a reason for you to use QPointer at all
I'll go one step further: I don't really see a reason for you to use
QObject
at all.In any case, in your specific case you can use
QList<QPointer<QObject>> performers;
and changePerformer* per = p.data();
toPerformer* per = reinterpret_cast<Performer*>(p.data());
-
@VRonin said in How to cast interfaces to QObjects?:
I don't really see a reason for you to use QObject at all.
Judging by what was posted, I'd agree.