为什么QObject会破坏被破坏的信号?

时间:2011-12-30 19:48:19

标签: c++ qt destructor

考虑这个测试用例:

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被销毁之前立即发出,并且无法阻止。”为什么会发生这种情况?< / p>

2 个答案:

答案 0 :(得分:24)

如果你考虑信号将如何发射,它是由基础QObject完成的 - 这就是QObject知道它被摧毁的方式。

因此,当派生类被销毁时,最派生的析构函数将首先运行(按照标准C ++ dtor处理),并显示"MyObject destructor"消息。当该dtor完成时,基本dtors运行,在这种情况下,它是QObject dtor,然后发出信号并显示"About to be destroyed!"消息。

您提到的文档中的措辞可能有点不精确。它的措辞可能更好,例如“当对象obj被破坏时发出此信号”或“在对象obj完全被破坏之前立即发出此信号”。

答案 1 :(得分:1)

迈克尔的回答是正确的,只要使用直接联系。

如果使用排队连接,则在主事件循环的下一次迭代中调用插槽。将其与发出信号的对象的析构函数相结合,很明显为什么结果与直接连接相同。

另见官方文件:

请注意,连接类型可能会影响线程编程。 (短版本:Direct在与信号相同的线程中执行槽,但排队在接收器线程中运行)