【发布时间】:2026-02-18 19:55:02
【问题描述】:
我有一个 QT 应用程序,其中几个不同的子组件需要从 Internet 获取数据。我想要一个Network 类来完成所有的网络交互,然后以某种方式通知调用者。我不知道如何使用插槽来做到这一点,所以我编写了一个回调解决方案:
void Network::downloadFile(QString& urlstr, const std::function<void (QString, QByteArray, QNetworkReply::NetworkError)>& callback) {
auto processDownload = [&]() {
QNetworkReply * reply = qobject_cast<QNetworkReply *>(sender());
QByteArray result;
QString filename = reply->url().fileName();
if (reply->error() == QNetworkReply::NoError) { // Success
result = reply->readAll();
}
callback(filename, result, reply->error());
reply->deleteLater();
};
QNetworkReply *reply = nam_->get(QNetworkRequest(QUrl(urlstr)));
connect(reply, &QNetworkReply::downloadProgress, this, &Network::downloadProgress);
connect(reply, &QNetworkReply::finished, this, processDownload);
}
但是,一旦调用callback,我就会收到段错误。我尝试了几种不同的方法来定义回调,即使它为空,它仍然会崩溃(主要是段错误,有时是错误的函数调用)。定义为:
std::function<void(QJsonObject, QNetworkReply::NetworkError)> f = std::bind(&MainWindow::onResult, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3);
我采取了类似static_cast<parent_class*>(this->parent())->onResult(..) 的方法,但这并不是很好的解耦。我怎样才能以可以传递(或发信号给)任何通用 std::function 的方式做到这一点?
编辑:Downloadfile 通常这样调用:
void MainWindow::DoNetworkRQ(QString url) {
std::function<void(QJsonObject, QNetworkReply::NetworkError)> f = std::bind(&MainWindow::onResult, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3);
network_.downloadFile(url, f);
}
这会导致段错误。如何以 QT 方式执行此操作?
【问题讨论】:
-
C++ 基础 - 您的
callback变量超出范围。复制它而不是只传递对 lambda 的引用。 -
我想访问对象实例,所以不能复制,对吧?什么是正确的“QT”方式来做到这一点? @chehrlic
-
您能否展示您如何调用
downloadFile,以便我们查看您为回调传递的内容? -
@JarMan 添加了详细信息
-
"我想访问对象实例,所以不能复制,对吧?" - 不知道你在说什么,但我说局部变量
callback超出范围,因为你只通过引用 lambda 传递它们,因此应用程序将崩溃。请阅读有关 lambda 捕获的信息。