如果指针指向一个新对象,信号/槽连接会发生什么 [英] What happens to the signal/slot connection if the pointer is pointing to a new object

查看:422
本文介绍了如果指针指向一个新对象,信号/槽连接会发生什么的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个上传者使用以下代码:

I have a uploader with the following code:

if(!_canceled) {
    _reply = _accessManager.put(request, item);

    if(_reply) { 
        _currentItem = item;

        bool status = connect(_reply, SIGNAL(uploadProgress(qint64, qint64)), this, SLOT(reportUploadProgress(qint64, qint64)));
        pantheios::log(pantheios::debug, "StorageProvider(): connection uploadProgress(qint64, qint64), status", pantheios::boolean(status));
        status = connect(_reply, SIGNAL(finished()), this, SLOT(handleFinishedRequest()));
        pantheios::log(pantheios::debug, "StorageProvider(): connection finished(), status", pantheios::boolean(status));

    } else {
        emit noReply();
        pantheios::log(pantheios::error, "StorageProvider(): no reply", item.toUtf8());
    }

然后在完成的插槽中我这样做:

Then in the finished slot I do this:

QNetworkReply *reply =  qobject_cast<QNetworkReply*>(sender());

if(reply->error() > QNetworkReply::NoError) { 
    pantheios::log(pantheios::error, "StorageProvider(handleFinishedRequest) ", reply->errorString().toUtf8());

    if((reply->error() == QNetworkReply::TemporaryNetworkFailureError) || (reply->error() == QNetworkReply::ContentReSendError)) {
                    // retry the last request
        _reply = accessManager.put(reply->request(), _currentItem);
    }

} else {
    ...
}

此StorageProvider将能够处理不同的请求,并且回复将有不同的连接,具体取决于创建什么函数。回复是一个成员变量的原因是,我可以在我做下一个请求之前删除它。

This StorageProvider will be able to handle different request and the reply will have different connections depending on in what function it is created. The reason why the reply is a member variable is so that I can delete it before I do my next request.

所以,我的问题是,如果我重新指定回复,我必须再次连接吗?插槽/信号是连接到指针还是对象?还有,有没有更好的方法来删除旧的回复?

So, my question is, do I have to do the connection again if I repoint the reply? Is the slot/signal connected to the pointer or the object? Also, is there any better way to delete the old reply?

编辑:将代码更改为完成请求的handeler;

Changed the code to this for the handeler of a finished request;

if(_currentReply->error() > QNetworkReply::NoError) { 
    pantheios::log(pantheios::error, "StorageProvider(handleFinishedRequest) ", _currentReply->errorString().toUtf8());

    if(((_currentReply->error() == QNetworkReply::TemporaryNetworkFailureError) || (_currentReply->error() == QNetworkReply::ContentReSendError)) && (_currentRetries < 4)) {

        QNetworkRequest lastRequest = _currentReply->request();
        _currentReply->deleteLater();

        _currentReply = _accessManager.put(lastRequest, _currentItem);

        if(_currentReply) { 

            bool status = connect(_currentReply, SIGNAL(uploadProgress(qint64, qint64)), this, SLOT(reportUploadProgress(qint64, qint64)));
            pantheios::log(pantheios::debug, "StorageProvider(retry): connection uploadProgress(qint64, qint64), status", pantheios::boolean(status));
            status = connect(_currentReply, SIGNAL(finished()), this, SLOT(handleFinishedRequest()));
            pantheios::log(pantheios::debug, "StorageProvider(retry): connection finished(), status", pantheios::boolean(status));

        } else {
            emit noReply();
            pantheios::log(pantheios::error, "StorageProvider(retry): AccessManager no reply");
        }
    }

}


推荐答案

信号连接到对象,而不是指针变量,因此您必须每次都建立新连接。

The signal is connected to the object, not to the pointer variable, so you have to make new connections each time.

回复,只需在 finished()槽的开头调用 deleteLater()

And to delete the reply, just call deleteLater() at the beginning of the finished() slot:

QNetworkReply *reply =  qobject_cast<QNetworkReply*>(sender());
reply->deleteLater();

这样,它将在插槽执行结束时被删除。

that way it will be deleted at the end of the slot execution.



您可以通过将每个请求(最初的加上所有重试)包含在其中来避免使用 sender()自己的 QObject 派生类:

class PutRequest : public QObject {
Q_OBJECT
private:
     QNetworkAccessManager *_manager;
     QNetworkReply *_reply;
     QIODevice *_item; // Or whatever type the second parameter of put is
public:
     explicit PutRequest(QNetworkAccessManager *manager, QNetworkRequest *request, QIODevice *item, QObject *parent = 0)
       : QObject(parent), _manager, _reply(0), _item(item) 
     {            
         _reply = _manager.put(request, item);
         connectSignalsAndSlots();
     }       

private:
     void connectSignalsAndSlots() {
         // to delete the reply if the PutRequest object is destroyed
         reply_->setParent(this);
         // since the reply is encapsulated, the object has to emit its own
         // upload progress signal
         connect(_reply, SIGNAL(uploadProgress(qint64, qint64)), this, SIGNAL(uploadProgress(qint64, qint64)));
         connect(_reply, SIGNAL(finished()), this, SLOT(handleFinishedRequest()));
     }

private slots:
     void handleFinishedRequest() {
         _reply->deleteLater();
         if(reply->error() != QNetworkReply::NoError) {
               pantheios::log(pantheios::error, "StorageProvider(handleFinishedRequest) ", reply->errorString().toUtf8());

         if((_reply->error() == QNetworkReply::TemporaryNetworkFailureError) || (reply->error() == QNetworkReply::ContentReSendError)) {
            // retry the last request
            _reply = _manager.put(_reply->request(), _item);
            connectSignalsAndSlots();
         }

         } else {
         ...                 
             emit finished(this);
         }         
     }
signals:
     void uploadProgress(qint64, qint64);
     // emitted when the upload is successful (after the possible retries)
     void finished(PutRequest*);
};

您可以这样创建请求:

if(!_canceled) {
    PutRequest *putRequest = new PutRequest(_accessManager, request, item);

    // and you connect putRequest object signals to whatever you connected _reply to

这篇关于如果指针指向一个新对象,信号/槽连接会发生什么的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆