Disconnect doesn't happen upon deletion



  • Hello,
    Qt document for QObject mentions that

    bq.
    QObject::~QObject () [virtual]
    All signals to and from the object are automatically disconnected, and any pending posted events for the object are removed from the event queue. However, it is often safer to use deleteLater() rather than deleting a QObject subclass directly.

    So I wrote a small piece of code just to verify this auto disconnect thing.

    SignalClass.h
    @#ifndef SIGNALCLASS_H
    #define SIGNALCLASS_H

    #include <QObject>

    class SignalClass : public QObject
    {
    Q_OBJECT
    public:
    explicit SignalClass (QObject *parent = 0);
    ~SignalClass ();

    private:
    void connectNotify (const char *signal);
    void disconnectNotify (const char *signal);

    signals:
    void sigNotification ();

    public slots:

    };

    #endif // SIGNALCLASS_H@

    SignalClass.cpp
    @#include <QDebug>
    #include "SignalClass.h"

    SignalClass::SignalClass (QObject *parent) :
    QObject(parent)
    {
    qDebug () << "SignalClass Constructor";
    }

    SignalClass::~SignalClass ()
    {
    qDebug () << "SignalClass Destructor";
    }

    void SignalClass::connectNotify (const char *signal)
    {
    qDebug () << "Signal Connected";
    }

    void SignalClass::disconnectNotify (const char *signal)
    {
    qDebug () << "Signal Disconnected";
    }@

    SlotClass.h
    @#ifndef SLOTCLASS_H
    #define SLOTCLASS_H

    #include <QObject>
    #include "SignalClass.h"

    class SlotClass : public QObject
    {
    Q_OBJECT
    public:
    explicit SlotClass (QObject *parent = 0);
    ~SlotClass ();
    void MakeConnection ();

    private:
    SignalClass signalObject;

    signals:

    public slots:
    void SlotNotification ();
    };

    #endif // SLOTCLASS_H@

    SlotClass.cpp
    @#include <QDebug>
    #include "SlotClass.h"

    SlotClass::SlotClass (QObject *parent) :
    QObject(parent)
    {
    qDebug () << "SlotClass Constructor";
    }

    SlotClass::~SlotClass ()
    {
    qDebug () << "SlotClass Destructor";
    }

    void SlotClass::MakeConnection ()
    {
    connect (&signalObject, SIGNAL(sigNotification()),
    this, SLOT(SlotNotification()));
    }

    void SlotClass::SlotNotification ()
    {

    }@

    Main.cpp
    @#include <QCoreApplication>
    #include <QDebug>
    #include "SlotClass.h"

    int main (int argc, char **argv)
    {
    QCoreApplication core (argc, argv);
    SlotClass *slotObject;

    slotObject = new SlotClass ();
    slotObject->MakeConnection ();
    slotObject->deleteLater ();
    
    return core.exec &#40;&#41;;
    

    }@

    Console Output
    SignalClass Constructor
    SlotClass Constructor
    Signal Connected
    SlotClass Destructor
    SignalClass Destructor

    From the console output, I see that signal-slot connection are not terminated or maybe I am missing something.



  • Hi, If your waiting for slotObject to be destroyed, it's when the program is terminated. (object gets destroyed when software block is closed, so below the return core.exec();)
    It might give you a better understanding of disconnect etc to create a MAinwindow and open/close a dialog in it. Then the "disconnect" should be seen in your output window in QtCreator or in you command terminal if running in terminal mode.
    Greetz



  • [quote author="Jeroentje@home" date="1369070646"]Hi, If your waiting for slotObject to be destroyed, it's when the program is terminated. (object gets destroyed when software block is closed, so below the return core.exec();)
    [/quote]

    Ok, in that case I modified the code like this,

    @#include <QCoreApplication>
    #include <QDebug>
    #include "SlotClass.h"

    int main (int argc, char **argv)
    {
    QCoreApplication core (argc, argv);
    SlotClass *slotObject;

    slotObject = new SlotClass ();
    slotObject->MakeConnection ();
    delete slotObject;
     
    return core.exec (&#41;;
    

    }@

    then also it makes no difference, produces same result. :-/


  • Lifetime Qt Champion

    You are deleting slotObject before the event loop starts thus you won't get anything related to signals and slots.



  • [quote author="SGaist" date="1369120421"]You are deleting slotObject before the event loop starts thus you won't get anything related to signals and slots.
    [/quote]

    what about code in first post, slotObject.deleteLater (); in that case object will be deleted by event loop and in that case i should also expect the signal, right.?

    Or may be *void disconnectNotify (const char signal); won't work for the object which is getting deleted, because if the object is deleted then all pending events are flushed, I think.


  • Lifetime Qt Champion

    It might also be deleted one the first loop, then was it completely "set up" ?
    Did you try to use QTimer::singleShot with a timeout of a second ?



  • [quote author="SGaist" date="1369125092"]It might also be deleted one the first loop, then was it completely "set up" ?
    Did you try to use QTimer::singleShot with a timeout of a second ?[/quote]

    sorry, didn't get you...


  • Lifetime Qt Champion

    Meaning: did you try something like

    @
    int main (int argc, char **argv)
    {
    QCoreApplication core (argc, argv);
    SlotClass *slotObject;

    slotObject = new SlotClass ();
    slotObject->MakeConnection ();
    
    QTimer::singleShot(1000, slotObject, SLOT(deleteLater()));
     
    return core.exec &#40;&#41;;
    

    }@

    ?



  • @SGaist, Yes, I tried the code that you mentioned, it gave me same result... :-)
    Timer deletes the slotObject after delay of 1 second but didn't see any disconnection prints.


  • Moderators

    When your slotObject is deleted, your signalObject is also deleted immediately (because it is a member variable!) -- that's why it has no time to call disconnectNotify().

    Separate the two objects and make sure that signalObject doesn't get destroyed with slotObject. You should see the debug message then:

    @
    int main(...)
    {
    ...
    SignalClass *signalObject = new SignalClass();
    SlotClass *slotObject = new SlotClass();

    QObject::connect(signalObject, SIGNAL(...), slotObject, SLOT(...));
    slotObject->deleteLater();
    ...
    

    }
    @


  • Lifetime Qt Champion

    Argle, I misread the code... Didn't saw that signalObject was a member object...



  • Ok, I removed signalObject from slotClass
    and modified main.cpp as follows,

    @int main (int argc, char **argv)
    {
    QCoreApplication core (argc, argv);
    SignalClass *signalObject;
    SlotClass *slotObject;

    signalObject = new SignalClass ();
    slotObject = new SlotClass ();
    
    QObject::connect (signalObject, SIGNAL(sigNotification()),
                      slotObject, SLOT(SlotNotification()));
    
    slotObject->deleteLater ();
    
    return core.exec (&#41;;
    

    }@

    It gave me,
    Console Output
    SignalClass Constructor
    SlotClass Constructor
    Signal Connected
    SlotClass Destructor


  • Moderators

    It looks like your program quit immediately. That would also not give signalObject time to call disconnectNotify() ;)

    Turn it into a GUI application and show a QWidget -- that will keep the program running until you close the window:

    @
    int main (int argc, char **argv)
    {
    QApplication a(argc, argv);
    QWidget w;
    w.show();

    SignalClass ...
    

    }
    @

    You'll also need to add "QT += widgets" (or "QT += gui" if you're using Qt 4) to your .pro file.

    I just tried this using Qt 5.0.2 in Windows, and it worked.



  • In that case I would say that I am running core.exec(), so surely program doesn't get terminated or quits immediately. Event loop keeps on running until I click the stop button in Qt creator.


  • Moderators

    Hmm... it might be a bug in Qt 4 or your platform (what OS are you using?). I made this is using Qt 5.0.2 (MSVC2012 x64) on Windows 8 x64:

    @
    class MyWidget : public QWidget
    {
    Q_OBJECT
    QString name;

    public:
    MyWidget(const QString& name, QWidget *parent = 0) : QWidget(parent), name(name)
    { qDebug() << name << "constructed"; }

    ~MyWidget()
    { qDebug() << name << "destroyed"; }
    

    protected:
    void connectNotify(const QMetaMethod &signal)
    { qDebug() << name << "connected to" << signal.name(); }

    void disconnectNotify(const QMetaMethod &signal)
    { qDebug() << name << "disconnected from" << signal.name(); }
    

    signals:
    void mySignal();

    public slots:
    void mySlot() {}
    };
    @

    @
    int main(int argc, char *argv[])
    {
    QApplication a(argc, argv);

    MyWidget *w1 = new MyWidget("w1");
    MyWidget *w2 = new MyWidget("w2");
    
    QObject::connect(w1, SIGNAL(mySignal()), w2, SLOT(mySlot()));
    
    w1->show();
    w2->deleteLater();
    
    return a.exec&#40;&#41;;
    

    }
    @

    Console output (Debug build)
    [quote]"w1" constructed
    "w2" constructed
    "w1" connected to "mySignal"
    "w1" connected to "objectNameChanged"
    "w2" destroyed
    "w1" disconnected from "mySignal"[/quote]

    Interestingly, I got this final line when I close the window in Qt 5.1.0 beta 1, but not Qt 5.0.2:
    [quote]"w1" disconnected from "objectNameChanged"[/quote]


Log in to reply
 

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