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. Trying to load a frame of widgets using a shared pointer
Forum Updated to NodeBB v4.3 + New Features

Trying to load a frame of widgets using a shared pointer

Scheduled Pinned Locked Moved Unsolved General and Desktop
5 Posts 5 Posters 133 Views 2 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.
  • L Offline
    L Offline
    leinad
    wrote last edited by
    #1

    Hi,

    I'm hoping you can help me. I built a library that is shared by many applications. This library contains a host of widgets which gives the users certain common options, so instead of creating the same widgets across applications they simply load the library and have all the widgets and logic already built in. The ui file was built in Qtcreator.

    If I call my library myWidgeLibrary, I was able to load the widgets in this manner

    WidgetLibrary *myWidgetLibrary;
    myWidgetLibrary = new WidgetLibary;
    
    //to load the library in the app I did something like this which works fine.
    ui->appGridLayout->addWidget( myWidgetLibrary, 0, 0, 1, 1 );
    
    

    So the above loads the widgetLibary into a gridLayout inside the users application.

    Now this is the issue. The people I work with does not like to use naked pointers.
    so "WidgetLibrary *myWidgetLibrary" is very bad.
    instead, they prefer the call the WidgetLibrary using a shared pointer.

    std::shared_ptr< WidgetLibrary > myWidgetLibrary ;
    ui->appGridLayout->addWidget( myWidgetLibrary, 0, 0, 1, 1 );
    
    

    But as you imagine that doesn't work and I get an error "No matching member function for call to 'addWidget' "
    I think because widgets are created with naked pointers and I'm trying to add them as a shared pointer.

    Would you know how I can fix this? What do I need to do in the library or in my main application to allow me to load it using a shared pointer?

    Any help would be appreciated!

    Thanks

    Christian EhrlicherC 1 Reply Last reply
    0
    • L leinad

      Hi,

      I'm hoping you can help me. I built a library that is shared by many applications. This library contains a host of widgets which gives the users certain common options, so instead of creating the same widgets across applications they simply load the library and have all the widgets and logic already built in. The ui file was built in Qtcreator.

      If I call my library myWidgeLibrary, I was able to load the widgets in this manner

      WidgetLibrary *myWidgetLibrary;
      myWidgetLibrary = new WidgetLibary;
      
      //to load the library in the app I did something like this which works fine.
      ui->appGridLayout->addWidget( myWidgetLibrary, 0, 0, 1, 1 );
      
      

      So the above loads the widgetLibary into a gridLayout inside the users application.

      Now this is the issue. The people I work with does not like to use naked pointers.
      so "WidgetLibrary *myWidgetLibrary" is very bad.
      instead, they prefer the call the WidgetLibrary using a shared pointer.

      std::shared_ptr< WidgetLibrary > myWidgetLibrary ;
      ui->appGridLayout->addWidget( myWidgetLibrary, 0, 0, 1, 1 );
      
      

      But as you imagine that doesn't work and I get an error "No matching member function for call to 'addWidget' "
      I think because widgets are created with naked pointers and I'm trying to add them as a shared pointer.

      Would you know how I can fix this? What do I need to do in the library or in my main application to allow me to load it using a shared pointer?

      Any help would be appreciated!

      Thanks

      Christian EhrlicherC Online
      Christian EhrlicherC Online
      Christian Ehrlicher
      Lifetime Qt Champion
      wrote last edited by Christian Ehrlicher
      #2

      @leinad said in Trying to load a frame of widgets using a shared pointer:

      Would you know how I can fix this

      Pass the naked pointer with .get() and wonder why it crashes as soon as your shared pointer goes out of scope.
      in other words - don't use a shared pointer for QObjects.

      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
      4
      • I Offline
        I Offline
        IgKh
        wrote last edited by
        #3

        As @Christian-Ehrlicher wrote, std::shared_ptr and QObjects don't mix. The reason for that is that once you add a widget to another widget's layout - the later will become the former' owner in the QObject hierarchy, and will therefore consider itself responsible to delete it when the time comes. At the same time the shared_ptr still thinks it manages the widget and will try to delete it when it deems necessary too. This means that one of the pointers to the widget pointer will become dangling at some point, which is a disaster for the program.

        For environments that have a "no bare pointers" rule, you can use std::unique_ptr to allocate objects (via std::make_unique), and then when you pass them to Qt ownership use the release method to have the unique pointer "give up" its' managed object. That said such a rule makes life a lot harder than needed in Qt code bases.

        1 Reply Last reply
        0
        • jeremy_kJ Offline
          jeremy_kJ Offline
          jeremy_k
          wrote last edited by
          #4

          QPointer and QObjectCleanupHandler might be of interest. They monitor rather than own QObject instances.

          Asking a question about code? http://eel.is/iso-c++/testcase/

          1 Reply Last reply
          0
          • S Offline
            S Offline
            SimonSchroeder
            wrote last edited by
            #5

            Pointers in Qt look naked, but they are not. As said before widgets own all their child widgets and handle them being cleaned up. And certainly there is a place in C++ for non-owning raw pointers. Don't use shared_ptr in every single place. If you call a function it is okay if it expects a raw pointer while you have the shared_ptr. If you start copying the shared_ptr into every function you call you will loose a lot of performance. Sure, you can use a const std::shared_ptr & instead, but that is also defeating the purpose and no different than raw pointers. Raw pointers are not evil, but owning raw pointers are.

            In your tiny example the raw pointer is owning for just a very short time (most likely only for the the two lines if there is nothing in between). If you want to be pedantic you could follow the approach of @IgKh and use a std::unique_ptr. But, it is most certainly mandatory to use std::make_unique to create the object. Otherwise allocation might still fail and throw an exception and the unique_ptr does not become the owner and the destructor of partially created objects (if you are using inheritance) are not called. You see from this that just using smart pointers does not always solve the problem because you can still use them wrong if you don't understand everything about them. And there is very little gain in your specific case in using a smart pointer (correctly). And for most programs it is true that they don't catch out-of-memory errors and handle them properly to free up some memory.

            I would personally never use smart pointers with Qt widget types. (Unless Qt in new versions rewrites their library to make them mandatory.)

            1 Reply Last reply
            1

            • Login

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