[SOLVED] Calling QObject::parent() fucks things up



  • Sorry for the rudeness but I can only describe the mess I'm in with this. Maybe it's something idiot I'm struggling with but I don't get it.

    Sorry for the pseudo-c++ but the real classes are quite big.
    I have :
    @
    class A : public QWidget
    {
    public:
    A(): x(0)
    {
    m_B = new B(this);
    }
    ~A();
    int someAMethod();

    private:
    B* m_B;
    int m_x;
    }

    class B : public QWidget
    {
    public:
    B(QWidget* parent): QWidget(parent)
    { }

    ~B();

    someBMethod()
    {
    int z = ((A*) parent())->someAMethod(); // end of the world starts here
    }
    }
    @

    Now, if my main instanciated A and if I called someBMethod() later in the program I would assume z to be A's m_x, i.e. 0.
    But that's not the case, and my program just becomes crazy : I start having random non-related segfaults (sometimes only at the call of someAMethod()), things don't display correctly, and other little pleasures of life.
    The thing that shocked me is that when I tried debugging this with gdb, things change when I call parent().

    To the point to when I was after the line
    @int z = ((A*) parent())->someAMethod();@
    in the code, the this pointer of the class wasn't even pointing to this class anymore, but to its parent.
    It's driving me insane, I even tried it on different computer and OSes to check for bad ram but it is the same comportment on :

    • linux 64bit w/ gcc 4.7
    • os x mountain lion w/ clang
    • windows with MinGW.

    I'm under qt5.0.1 but I had already this problem in 4.8.

    The worst is that if I write B like this :
    @
    class B : public QWidget
    {
    public:
    B(QWidget* parent): QWidget(parent)
    {
    m_parent = parent;
    }

    ~B();

    someBMethod()
    {
    int z = ((A*) m_parent)->someAMethod(); // end of the world starts here
    }

    private:
    QWidget* m_parent;
    }
    @

    everything works perfectly.

    Help me please.



  • In 'someBMethod()' you will call 'someAMethod()' pass a pointer for A in the B constructor and avoid use the cast.

    Like this:

    [code]
    class A ...

    class B : public QWidget
    {
      public:
       B(QWidget* parent): QWidget(parent)
       {
          m_parent = parent;
        }
     
       ~B();
     
       someBMethod()
        {
           int z = aParent->someAMethod(); // end of the world starts here
        }
     
    private:
     A* m_parent;
    }
    

    [/code]

    But the best solution is use Signal/Slot mechanism

    []'s



  • Yes but why doesn't QObject::parent() work ?


  • Moderators

    [quote author="doom_Oo7" date="1364424445"]
    @
    int z = ((A*) parent())->someAMethod(); // end of the world starts here
    @

    ...

    Yes but why doesn’t QObject::parent() work ?
    [/quote]

    QObject::parent() is fine; it's the casting that's the issue.

    C-style casts are unsafe, and have led to strange bugs in the past. In general C++, use static_cast() or dynamic_cast() instead. (Sometimes you might need reinterpret_cast(), but it's very unlikely)

    If you really want to type-cast QWidgets (or any other QObject), use a "qobject_cast()":http://qt-project.org/doc/qt-5.0/qtcore/qobject.html#qobject_cast


  • Moderators

    Also, parent() returns a parent QObject, and since your class is not a QObject (just because you inherit QWidget doesn't make it QObject, you need Q_OBJECT macro), it might lead to strange bahaviour.
    After you add Q_OBJECT you should (like JKSH said) use qobject_cast, which will return 0 and not blow up if the cast fails like the C-style cast you are using.

    There is also a QWidget::parentWidget() so you can use it for widgets instead of QObject::parent().



  • Okay, thanks.

    I had not written it in the pseudo code but my real classes were in fact Q_OBJECT, so using qobject_cast works. Thanks!


Log in to reply
 

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