在单独的插槽中删除发件人

时间:2012-05-14 03:39:50

标签: c++ qt memory-management signals-slots

我有一个发出3种不同信号的物体,我想传输这些信号以及删除它们的发送者。该对象位于另一个将充当这些信号发射器的对象中。

通常我会这样:

void SomeClass::someSideFunction() {
    Request* request = _StorageProvider.insert("somedata");

    connect(request, SIGNAL(succeded()),        this, SLOT(handleSucceded()));
    connect(request, SIGNAL(failed()),          this, SLOT(handleFailed()));
    connect(request, SIGNAL(alreadyExists()),   this, SLOT(handleAlreadyExists()));
}

void SomeClass::handleSucceded() {
    Request* request = qobject_cast<Request*>(sender());
    if(request != NULL) request ->deleteLater();
    emit succeded();
}

void SomeClass::handleFailed() {
    Request* request = qobject_cast<Request*>(sender());
    if(request != NULL) request ->deleteLater();
    emit failed();
}

void SomeClass::handleAlreadyExists() {
    Request* request = qobject_cast<Request*>(sender());
    if(request != NULL) request ->deleteLater();
    emit alreadyExists();
}

有更好的方法吗?即使“request”是storageProvider的子代,也有很多请求可以让我等待删除它们直到父级死掉。

我在考虑这样的解决方案:

connect(request, SIGNAL(succeded()),        this, SIGNAL(succeded()));
connect(request, SIGNAL(failed()),          this, SIGNAL(failed()));
connect(request, SIGNAL(alreadyExists()),   this, SIGNAL(alreadyExists()));
connect(request, SIGNAL(succeded()),        this, SLOT(memoryHnadler()));
connect(request, SIGNAL(failed()),          this, SLOT(memoryHnadler()));
connect(request, SIGNAL(alreadyExists()),   this, SLOT(memoryHnadler()));

如果发件人存在,内存处理程序将删除发件人。这种方法的缺点是什么,可能是更好的方法?

请注意,对象在完成后才会发出其中一个信号!

2 个答案:

答案 0 :(得分:3)

一个选项是让请求使用QObject :: deleteLater()安排自己的删除。像这样:

void Request::emitSucceeded() {
    emit succeeded();
    deleteLater();
}

void Request::emitFailed(int errorCode, const QString& errorString ) {
    m_errorCode = errorCode;
    m_errorString = errorString;
    emit failed();
    deleteLater();
}

例如,KDELib的异步操作基类KJob正在使用此模式(除非通过setAutoDelete(false)显式禁用)。

答案 1 :(得分:2)

我看不出你的第二种方法有什么缺点。 Qt将首先发送信号,然后发送内存处理程序,因为它的执行顺序与声明连接的顺序相同。

内存处理程序必须是唯一删除Request对象的内容。

另一种方法是使用Request对象作为参数发出信号,然后依靠用户槽来删除它们。但如果没有声明用户槽,你将保持内存增长......