如果指针指向一个新对象,信号/槽连接会发生什么 [英] What happens to the signal/slot connection if the pointer is pointing to a new object
问题描述
我有一个上传者使用以下代码:
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屋!