Consider this test case:
class MyObject : public QObject
{
Q_OBJECT
public:
MyObject() { qDebug() << "MyObject constructor"; }
virtual ~MyObject() { qDebug() << "MyObject destructor"; }
};
class Tracker : public QObject
{
Q_OBJECT
public:
Tracker() {}
public slots:
void onDestructor() { qDebug() << "About to be destroyed!"; }
};
int main(int argc, char** argv)
{
QCoreApplication app(argc, argv);
Tracker tracker;
MyObject *obj = new MyObject();
QObject::connect(obj, SIGNAL(destroyed()), &tracker, SLOT(onDestructor()));
delete obj;
return app.exec();
}
It prints this:
MyObject constructor
MyObject destructor
About to be destroyed!
This behaviour contradicts the Qt documentation: "This signal is emitted immediately before the object obj is destroyed, and can not be blocked." Why does this happen?
If you think about how the signal would get emitted, it's done by the base QObject - that's how the QObject knows it's being destroyed.
So when the derived class is destroyed, the most derived destructor gets run first (per standard C++ dtor handling), and the "MyObject destructor"
message is displayed. When that dtor completes, the base dtors get run and in this case that's the QObject dtor, which then emits the signal and the "About to be destroyed!"
message is displayed.
The wording in the docs you mentioned might be a bit imprecise. It might be better worded with something like, "This signal is emitted as the object obj is destroyed" or "This signal is emitted immediately before the object obj is completely destroyed".
Michael's answer is correct insofar direct connections are used.
If queued connections are used, the slots are called at the next iteration of the main event loop. Combine that with the destructor of the object emitting the signal, it becomes obvious why the result is the same as for direct connections are involved.
See also the official docs:
- Signals and Slots
- Connection Type
Note that Connection type may have consequences for threaded programming. (Short version: Direct executes slot in the same thread as the signal, but queued runs in the receiver thread)