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. When to setParent on injected QObjects?
QtWS25 Last Chance

When to setParent on injected QObjects?

Scheduled Pinned Locked Moved General and Desktop
parentchildqobject
6 Posts 3 Posters 3.5k Views
  • 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.
  • S Offline
    S Offline
    shavera
    wrote on 23 Jun 2015, 19:30 last edited by
    #1

    This is maybe a more philosophical/architectural question, but suppose I have a class

    class foo : public QObject{
    public: 
        foo(dependency* child) : m_child(child), QObject() {}
    
        foo* makeFoo(){
            dependency* child = new dependency;
            return new foo(child);
        }
    private:
        dependency* m_child;
    }
    

    Is it better to, in the constructor, set parent-child relationships (eg:

    foo::foo(dependency* child) : m_child(child), QObject(){
        m_child->setParent(this);
    }
    

    or to set the relationship in the factory construction?

    foo* foo::makeFoo(){
        dependency* child = new dependency;
        foo* _foo = new foo(child);
        child->setParent(_foo);
        return _foo;
    }
    

    I am pretty sure that they are functionally equivalent, but from a broader architectural stance, where should this relationship be set?

    A 1 Reply Last reply 23 Jun 2015, 21:07
    0
    • C Offline
      C Offline
      Chris Kawa
      Lifetime Qt Champion
      wrote on 23 Jun 2015, 21:01 last edited by Chris Kawa
      #2

      Just for the sake of consistency - it's highly unusual for a QObject derived class to take a child as a constructor parameter. They usually take a parent. For someone not familiar with your code, but familiar with Qt, something like new Foo(bar) would look like an instance of class Foo having a parent bar, which is the other way around in your code.

      If you're planning to expose construction of class via make function then what's the point of passing a child as param at all? the object can create that child as part of its usual construction.

      So my personal take on that design would be something like this:

      class Foo : public QObject
      {
      public: 
         static Foo* makeFoo(QObject* parent = nullptr) { return new Foo(parent); }
      protected:
          Foo(QObject* parent) : QObject(parent) {}
      private:
          Dependency m_child;
      }
      

      Or, if you feel for whatever reason the child needs to be allocated dynamically (ask yourself really hard does it), something like this:

      class Foo : public QObject
      {
      public: 
         static Foo* makeFoo(QObject* parent = nullptr) { return new Foo(parent); }
      protected:
          //assuming Dependency takes parent as a constructor param
          Foo(QObject* parent) : QObject(parent), m_child(new Dependency(this)) {} 
      private:
          Dependency* m_child;
      }
      
      S 1 Reply Last reply 25 Jun 2015, 15:09
      1
      • S shavera
        23 Jun 2015, 19:30

        This is maybe a more philosophical/architectural question, but suppose I have a class

        class foo : public QObject{
        public: 
            foo(dependency* child) : m_child(child), QObject() {}
        
            foo* makeFoo(){
                dependency* child = new dependency;
                return new foo(child);
            }
        private:
            dependency* m_child;
        }
        

        Is it better to, in the constructor, set parent-child relationships (eg:

        foo::foo(dependency* child) : m_child(child), QObject(){
            m_child->setParent(this);
        }
        

        or to set the relationship in the factory construction?

        foo* foo::makeFoo(){
            dependency* child = new dependency;
            foo* _foo = new foo(child);
            child->setParent(_foo);
            return _foo;
        }
        

        I am pretty sure that they are functionally equivalent, but from a broader architectural stance, where should this relationship be set?

        A Offline
        A Offline
        alex_malyu
        wrote on 23 Jun 2015, 21:07 last edited by alex_malyu
        #3

        I would vote for explicit addChild(Object * ) if you really need to expose adding children functionality outside of the class

        1 Reply Last reply
        1
        • C Chris Kawa
          23 Jun 2015, 21:01

          Just for the sake of consistency - it's highly unusual for a QObject derived class to take a child as a constructor parameter. They usually take a parent. For someone not familiar with your code, but familiar with Qt, something like new Foo(bar) would look like an instance of class Foo having a parent bar, which is the other way around in your code.

          If you're planning to expose construction of class via make function then what's the point of passing a child as param at all? the object can create that child as part of its usual construction.

          So my personal take on that design would be something like this:

          class Foo : public QObject
          {
          public: 
             static Foo* makeFoo(QObject* parent = nullptr) { return new Foo(parent); }
          protected:
              Foo(QObject* parent) : QObject(parent) {}
          private:
              Dependency m_child;
          }
          

          Or, if you feel for whatever reason the child needs to be allocated dynamically (ask yourself really hard does it), something like this:

          class Foo : public QObject
          {
          public: 
             static Foo* makeFoo(QObject* parent = nullptr) { return new Foo(parent); }
          protected:
              //assuming Dependency takes parent as a constructor param
              Foo(QObject* parent) : QObject(parent), m_child(new Dependency(this)) {} 
          private:
              Dependency* m_child;
          }
          
          S Offline
          S Offline
          shavera
          wrote on 25 Jun 2015, 15:09 last edited by
          #4

          @Chris-Kawa
          The reason I inject it is primarily for testing. Dependency injection allows me to inject mock objects at runtime. (Also, dependency injection as a general design principle for modularization, etc)

          I can see the point in doing it in reverse, but in that case, I have to do explicit checks in the parent class as to whether the child class was injected or not. (eg:)

          class Foo{ // with all attendent other stuff
          public:
          void DoStuff(){
            Dependency* child = findChild<Dependency*>();
            if(nullptr != child){
              child->doStuff;
            }
          };
          

          Which... I mean... works, but is really bloated to keep checking for children....

          Oh: I just checked, there is a "childEvent" function in QObject, that I guess I could use to inject-at-runtime the class, but still seems like trying to bend my code to fit Qt, rather than Qt following some pretty standard coding paradigms.

          1 Reply Last reply
          0
          • C Offline
            C Offline
            Chris Kawa
            Lifetime Qt Champion
            wrote on 25 Jun 2015, 15:55 last edited by
            #5

            I might be missing something but I'm not getting your point. In your original code you'd have to do the nullptr check just as well, because the child passed in the constructor could be nullptr.

            S 1 Reply Last reply 29 Jun 2015, 18:55
            0
            • C Chris Kawa
              25 Jun 2015, 15:55

              I might be missing something but I'm not getting your point. In your original code you'd have to do the nullptr check just as well, because the child passed in the constructor could be nullptr.

              S Offline
              S Offline
              shavera
              wrote on 29 Jun 2015, 18:55 last edited by
              #6

              @Chris-Kawa That's a valid point I hadn't considered. I'll just have to give this some more thought.

              It seems like maybe the most "Qt-correct" design would be to override childEvent(QChildEvent* event) to take the pointer into the member object when a child is added to the parent object. This would then, at least, bypass the need to call "findChild" over and over again.

              1 Reply Last reply
              0

              5/6

              25 Jun 2015, 15:55

              • Login

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