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 upcast a QPointer<Descendant>
Forum Updated to NodeBB v4.3 + New Features

How to upcast a QPointer<Descendant>

Scheduled Pinned Locked Moved Solved General and Desktop
7 Posts 5 Posters 410 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.
  • ocgltdO Offline
    ocgltdO Offline
    ocgltd
    wrote on last edited by ocgltd
    #1

    I have declared a class B, and a descendant class D. I also have a method:

    myMethod(QPointer<B> param1) {}
    

    When I try to call myMethod() with a QPointer to D as the parameter, the compiler complains that:

    cannot convert `QPointer<D>' to 'QPointer<B>'
    

    Why is it complaining? I thought passing a QPointer<D> will implicitly upcast it to QPointer<B>. How should I resolve this?

    jsulmJ 1 Reply Last reply
    0
    • ocgltdO ocgltd

      My method will create a singleton which uses a QPointer to the original object, When the method returns, the singleton survives and keeps using that QPointer. If something else in my code deletes the original object, I want to ensure the singleton's QPointer becomes null. So I thought that I must pass QPointer to Qpointer along the call chain to ensure weak/strong references remain intact, so the singleton's QPointer will switch to null when the original object is deleted.

      But if I understand the above correct, I can pass QPointer to standard pointer to QPointer, and all of the QPointers will switch to null when the original object is deleted.

      Pl45m4P Offline
      Pl45m4P Offline
      Pl45m4
      wrote on last edited by Pl45m4
      #6

      @ocgltd said in How to upcast a QPointer<Descendant>:

      But if I understand the above correct, I can pass QPointer to standard pointer to QPointer, and all of the QPointers will switch to null when the original object is deleted.

      This below says everything you need to know about QPointer.

      A guarded pointer, QPointer<T>, behaves like a normal C++ pointer T *, except that it is automatically cleared when the referenced object is destroyed (unlike normal C++ pointers, which become "dangling pointers" in such cases). T must be a subclass of QObject.

      Guarded pointers are useful whenever you need to store a pointer to a QObject that is owned by someone else, and therefore might be destroyed while you still hold a reference to it. You can safely test the pointer for validity.

      A guarded pointer will automatically cast to a T *, so you can freely mix guarded and unguarded pointers.

      ( https://doc.qt.io/qt-6/qpointer.html#details )

      Also it's mentioned that QPointer< T > is equally-comparable with T *, so like @Christian-Ehrlicher said, you can use it wherever a pointer is expected.
      The convenient bonus is that it's guarded and you can store it without worrying that it might point to free'd memory, because the original T obj has been deleted by its owner.
      (That's why it only works with QObject based types)

      So I thought that I must pass QPointer to Qpointer along the call chain to ensure weak/strong references remain intact, so the singleton's QPointer will switch to null when the original object is deleted.

      Shouldn't make any difference.
      If you pass/cast QPointer<A> --> A* --> QPointer<A>, the 2nd QPointer<A> is still guarded and watches the lifetime of A, since it's created from a pointer to A and they all three point to the same location.
      --> "equally-comparable" ;-)

      Edit:

      In case of future readers:

      From looking at the QPointer source code, it's easy to see how it works.
      For every operation (operators, move/copy/assignment c'tors) the QPointer's internal data is used, which is nothing more than the raw pointer.

      • https://codebrowser.dev/qt6/qtbase/src/corelib/kernel/qpointer.h.html

      If debugging is the process of removing software bugs, then programming must be the process of putting them in.

      ~E. W. Dijkstra

      1 Reply Last reply
      1
      • ocgltdO ocgltd

        I have declared a class B, and a descendant class D. I also have a method:

        myMethod(QPointer<B> param1) {}
        

        When I try to call myMethod() with a QPointer to D as the parameter, the compiler complains that:

        cannot convert `QPointer<D>' to 'QPointer<B>'
        

        Why is it complaining? I thought passing a QPointer<D> will implicitly upcast it to QPointer<B>. How should I resolve this?

        jsulmJ Offline
        jsulmJ Offline
        jsulm
        Lifetime Qt Champion
        wrote on last edited by
        #2

        @ocgltd From the documentation:
        "*A guarded pointer will automatically cast to a T *, so you can freely mix guarded and unguarded pointers. This means that if you have a QPointer<QWidget>, you can pass it to a function that requires a QWidget . For this reason, it is of little value to declare functions to take a QPointer as a parameter; just use normal pointers. Use a QPointer when you are storing a pointer over time.".

        https://forum.qt.io/topic/113070/qt-code-of-conduct

        1 Reply Last reply
        2
        • ocgltdO Offline
          ocgltdO Offline
          ocgltd
          wrote on last edited by
          #3

          From what I've found online this should work as I describe above in Qt6.6 and later (yet it doesn't for me). I've also seen answers to pass qptr.data() to the function - which I can confirm does work. I pass a QPointer to the method because it will create an object with lifespan beyond the return of the method, so are you saying just copy the regular pointer back to QPointer in the method? And if I do so, will all strong/weak references to the underlying object continue to work properly? (Transfer from QPointer to regular pointer to Qpointer)

          1 Reply Last reply
          0
          • Christian EhrlicherC Offline
            Christian EhrlicherC Offline
            Christian Ehrlicher
            Lifetime Qt Champion
            wrote on last edited by
            #4

            Since QPointer does no refcounting I don't see a problem here but also don't understand your lifespan problem.

            Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
            Visit the Qt Academy at https://academy.qt.io/catalog

            1 Reply Last reply
            1
            • ocgltdO Offline
              ocgltdO Offline
              ocgltd
              wrote on last edited by ocgltd
              #5

              My method will create a singleton which uses a QPointer to the original object, When the method returns, the singleton survives and keeps using that QPointer. If something else in my code deletes the original object, I want to ensure the singleton's QPointer becomes null. So I thought that I must pass QPointer to Qpointer along the call chain to ensure weak/strong references remain intact, so the singleton's QPointer will switch to null when the original object is deleted.

              But if I understand the above correct, I can pass QPointer to standard pointer to QPointer, and all of the QPointers will switch to null when the original object is deleted.

              Pl45m4P JonBJ 2 Replies Last reply
              0
              • ocgltdO ocgltd

                My method will create a singleton which uses a QPointer to the original object, When the method returns, the singleton survives and keeps using that QPointer. If something else in my code deletes the original object, I want to ensure the singleton's QPointer becomes null. So I thought that I must pass QPointer to Qpointer along the call chain to ensure weak/strong references remain intact, so the singleton's QPointer will switch to null when the original object is deleted.

                But if I understand the above correct, I can pass QPointer to standard pointer to QPointer, and all of the QPointers will switch to null when the original object is deleted.

                Pl45m4P Offline
                Pl45m4P Offline
                Pl45m4
                wrote on last edited by Pl45m4
                #6

                @ocgltd said in How to upcast a QPointer<Descendant>:

                But if I understand the above correct, I can pass QPointer to standard pointer to QPointer, and all of the QPointers will switch to null when the original object is deleted.

                This below says everything you need to know about QPointer.

                A guarded pointer, QPointer<T>, behaves like a normal C++ pointer T *, except that it is automatically cleared when the referenced object is destroyed (unlike normal C++ pointers, which become "dangling pointers" in such cases). T must be a subclass of QObject.

                Guarded pointers are useful whenever you need to store a pointer to a QObject that is owned by someone else, and therefore might be destroyed while you still hold a reference to it. You can safely test the pointer for validity.

                A guarded pointer will automatically cast to a T *, so you can freely mix guarded and unguarded pointers.

                ( https://doc.qt.io/qt-6/qpointer.html#details )

                Also it's mentioned that QPointer< T > is equally-comparable with T *, so like @Christian-Ehrlicher said, you can use it wherever a pointer is expected.
                The convenient bonus is that it's guarded and you can store it without worrying that it might point to free'd memory, because the original T obj has been deleted by its owner.
                (That's why it only works with QObject based types)

                So I thought that I must pass QPointer to Qpointer along the call chain to ensure weak/strong references remain intact, so the singleton's QPointer will switch to null when the original object is deleted.

                Shouldn't make any difference.
                If you pass/cast QPointer<A> --> A* --> QPointer<A>, the 2nd QPointer<A> is still guarded and watches the lifetime of A, since it's created from a pointer to A and they all three point to the same location.
                --> "equally-comparable" ;-)

                Edit:

                In case of future readers:

                From looking at the QPointer source code, it's easy to see how it works.
                For every operation (operators, move/copy/assignment c'tors) the QPointer's internal data is used, which is nothing more than the raw pointer.

                • https://codebrowser.dev/qt6/qtbase/src/corelib/kernel/qpointer.h.html

                If debugging is the process of removing software bugs, then programming must be the process of putting them in.

                ~E. W. Dijkstra

                1 Reply Last reply
                1
                • ocgltdO ocgltd has marked this topic as solved on
                • ocgltdO ocgltd

                  My method will create a singleton which uses a QPointer to the original object, When the method returns, the singleton survives and keeps using that QPointer. If something else in my code deletes the original object, I want to ensure the singleton's QPointer becomes null. So I thought that I must pass QPointer to Qpointer along the call chain to ensure weak/strong references remain intact, so the singleton's QPointer will switch to null when the original object is deleted.

                  But if I understand the above correct, I can pass QPointer to standard pointer to QPointer, and all of the QPointers will switch to null when the original object is deleted.

                  JonBJ Offline
                  JonBJ Offline
                  JonB
                  wrote on last edited by JonB
                  #7

                  @ocgltd said in How to upcast a QPointer<Descendant>:

                  If something else in my code deletes the original object, I want to ensure the singleton's QPointer becomes null.

                  You know this is the case if you use a QSharedPointer? Actually if you really want elsewhere's deletion to set your copy to nullptr it does not do that, but it is for sharing and delete-on-last-no-reference. So maybe not what you want :) So just mentioning it in case :) QPointer only allows for QObject objects, nulling on destruction/destroyed().

                  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