Почему сигнал уничтожения QObject называется ПОСЛЕ разрушения? - PullRequest
11 голосов
/ 30 декабря 2011

Рассмотрим этот тестовый пример:

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();
}

Он печатает это:

MyObject constructor
MyObject destructor
About to be destroyed!

Это поведение противоречит документации Qt: "Этот сигнал испускается немедленно перед объект obj уничтожен и не может быть заблокирован. " Почему это происходит?

Ответы [ 2 ]

24 голосов
/ 30 декабря 2011

Если вы думаете о том, как сигнал будет излучаться, это делается базовым QObject - вот как QObject знает, что он уничтожается.

Таким образом, когда производный класс уничтожается, сначала запускается наиболее производный деструктор (в соответствии со стандартной обработкой dtor в C ++), и отображается сообщение "MyObject destructor".Когда этот dtor завершается, запускаются базовые dtors, и в этом случае это dtor QObject, который затем излучает сигнал, и отображается сообщение "About to be destroyed!".

Текст в упомянутых вами документах может быть немногонеточный.Лучше было бы сформулировать что-то вроде: «Этот сигнал испускается, когда объект obj уничтожен» или «Этот сигнал испускается непосредственно перед тем, как объект obj полностью уничтожен».

1 голос
/ 01 июня 2018

Ответ Михаэля верен, если используются прямые соединения.

Если используются соединения в очереди, слоты вызываются на следующей итерации цикла основного события.Объедините это с деструктором объекта, излучающего сигнал, становится очевидным, почему результат такой же, как и для прямых соединений.

См. Также официальные документы:

Обратите внимание, что тип соединения может иметь последствия для многопоточного программирования.(Краткая версия: Direct выполняет слот в том же потоке, что и сигнал, но в очереди работает в потоке получателя)

...