Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. How to cast interfaces to QObjects?
Forum Updated to NodeBB v4.3 + New Features

How to cast interfaces to QObjects?

Scheduled Pinned Locked Moved Unsolved General and Desktop
9 Posts 6 Posters 2.4k Views 3 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • K Offline
    K Offline
    kitfox
    wrote on last edited by kitfox
    #1

    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.

    raven-worxR 1 Reply Last reply
    0
    • K kitfox

      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.

      raven-worxR Offline
      raven-worxR Offline
      raven-worx
      Moderators
      wrote on last edited by
      #2

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

      --- SUPPORT REQUESTS VIA CHAT WILL BE IGNORED ---
      If you have a question please use the forum so others can benefit from the solution in the future

      1 Reply Last reply
      0
      • K Offline
        K Offline
        kitfox
        wrote on last edited by kitfox
        #3

        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.

        1 Reply Last reply
        0
        • K Offline
          K Offline
          kuzulis
          Qt Champions 2020
          wrote on last edited by kuzulis
          #4

          You need to use Q_OBJECT macto too. Otherwise, qobject_cast<> will fails.

          1 Reply Last reply
          0
          • A Offline
            A Offline
            Asperamanca
            wrote on last edited by
            #5

            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

            1 Reply Last reply
            0
            • K Offline
              K Offline
              kitfox
              wrote on last edited by
              #6

              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()); }
              
              kshegunovK 1 Reply Last reply
              0
              • K kitfox

                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()); }
                
                kshegunovK Offline
                kshegunovK Offline
                kshegunov
                Moderators
                wrote on last edited by
                #7

                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.

                Read and abide by the Qt Code of Conduct

                VRoninV 1 Reply Last reply
                0
                • kshegunovK kshegunov

                  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.

                  VRoninV Offline
                  VRoninV Offline
                  VRonin
                  wrote on last edited by VRonin
                  #8

                  @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());

                  "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                  ~Napoleon Bonaparte

                  On a crusade to banish setIndexWidget() from the holy land of Qt

                  kshegunovK 1 Reply Last reply
                  0
                  • VRoninV VRonin

                    @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());

                    kshegunovK Offline
                    kshegunovK Offline
                    kshegunov
                    Moderators
                    wrote on last edited by
                    #9

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

                    Read and abide by the Qt Code of Conduct

                    1 Reply Last reply
                    0

                    • Login

                    • Login or register to search.
                    • First post
                      Last post
                    0
                    • Categories
                    • Recent
                    • Tags
                    • Popular
                    • Users
                    • Groups
                    • Search
                    • Get Qt Extensions
                    • Unsolved