找到`destroyed(QObject*)`信号的发送者

Kam*_*jii 5 c++ qt signals-slots

我目前想知道如何合理地使用QObject::destroyed(QObject*) 信号.

一个观察

我注意到 - QWidget衍生物体的处理略有不同.考虑以下小型自包含和编译示例:

/* sscce.pro:
QT += core gui widgets
CONFIG += c++11
TARGET = sscce
TEMPLATE = app
SOURCES += main.cpp
*/

#include <QApplication>
#include <QPushButton>
#include <QTimer>
#include <QtDebug>

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

    QPushButton *button = new QPushButton;
    QObject::connect(button, &QPushButton::destroyed,
        [=](QObject *o) { qDebug() << o; });

    delete button;

    QTimer *timer = new QTimer;
    QObject::connect(timer, &QTimer::destroyed,
        [=](QObject *o) { qDebug() << o; });

    delete timer;

    return app.exec();
}
Run Code Online (Sandbox Code Playgroud)

这是它的输出:

QWidget(0x1e9e1e0)
QObject(0x1e5c530)

所以可能是信号是从QObjectd-tor 发出的,所以QObject当调用插槽时只剩下基座QTimer.然而,它QWidget的d-tor似乎是拦截的,因为它仍然将自己标识为QWidget来自插槽.

而问题

假设我们有一个计时器池,用于组织以下几个计时器QList<QTimer *>:

struct Pool {
    QTimer *getTimer() {
        return timers.at(/* some clever logic here */);
    }        

    QList<QTimer *> timers;
};
Run Code Online (Sandbox Code Playgroud)

现在,一个不谨慎的用户可能会删除借给他/她的计时器.好吧,我们可以做出反应并简单地从列表中删除该计时器.一个插槽可以解决这个问题:

Pool::Pool() {
    /* for each timer created */
    connect(theTimer, SIGNAL(destroyed(QObject*),
        this, SLOT(timerDestroyed(QObject*));
}

void Pool::timerDeleted(QObject *object) {
    QTimer *theTimer = /* hrm. */
    timers.removeOne(theTimer);
}
Run Code Online (Sandbox Code Playgroud)

但现在呢?人力资源管理.当调用插槽时,QTimer已经处于破坏状态并且部分被破坏 - 只剩下它的QObject基础.所以我不可能qobject_cast<QTimer *>(object).

要解决此问题,我可以考虑以下技巧:

  1. QObjects 存储在列表中.然后,每次我使用列表中的项目时,我都必须向下转发.static_cast但是,这可以使用,因为我知道QTimer列表中只有s,所以不需要dynamic_castqobject_cast.
  2. Insteat removeOne使用a遍历列表iterator,然后QTimer直接比较每个项目QObject.然后使用QList::erase或等.
  3. static_cast甚至reinterpret_castQObject一个Qtimer仍然.

我该怎么办?

谢谢,圣诞快乐,新年快乐: - )[*]

[*]:这个问题完成后会清理它.

Chu*_*nch 1

如果您正在寻找技巧,您可以简单地使用基本 QObject objectName 并基于此删除已销毁的计时器。