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.


  • Moderators

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



  • This is not working for me. I get invalid static_cast from type 'QObject*' to type 'Performer*' whenever I try to assign my QPointer<Performer> to a Perfomer* pointer, even if I use Q_DECLARE_INTERFACE.



  • 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()); }
    

  • Qt Champions 2017

    You can't use anything with QPointer, it has to be specifically a QObject.

    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 QObjects, then just make the base class a QObject.



  • @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 change Performer* per = p.data(); to Performer* per = reinterpret_cast<Performer*>(p.data());


  • Qt Champions 2017

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


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.