QtConcurrent 错误:对非静态成员的引用
Posted
技术标签:
【中文标题】QtConcurrent 错误:对非静态成员的引用【英文标题】:QtConcurrent error: reference to non-static member 【发布时间】:2013-08-11 20:17:36 【问题描述】:我在装有 OS-X 10.8.4 的 Mac 上运行 Qt 5.1 和 QtQuick 2.0。
我的 Qt-QML GUI 变得无响应,因为我用文件 I/O 操作阻塞了事件循环。解决它的常用方法是使用多线程,正如 Will Bickford 所讨论的 HERE。
为此,我尝试使用:
QtConcurrent::blockingMapped()
这比使用显式 QFuture 对象更简单。我一直在阅读Qt docs 和cool examples 并得到以下代码工作(仿照example):
// NOTE: this all seems to work:
#include <QList>
#include <iostream>
#include "dataobject.h"
#include <QtConcurrent/QtConcurrentMap>
DataObject load(const QString &file)
std::cout << "File I/O in thread = " << QThread::currentThread() << std::endl;
return DataObject anObject(file);
int main(int argc, char *argv[])
...
// Create a list of filenames:
int count = 5;
QList<QString> allFiles;
for (int i = 0; i < count; i++)
allFiles.append(QString("aFileName"));
std::cout << "# of files = " << allFiles.size() << std::endl;
QList<DataObject> allTheDataObjects = QtConcurrent::blockingMapped(allFiles,load);
std::cout << "# of objects = " << allTheDataObjects.size() << std::endl;
...
这里是 DataObject 的头文件和实现文件:
#include <QString>
class DataObject
public:
DataObject();
DataObject(QString filename);
QString theFileName;
;
#include "dataobject.h"
DataObject::DataObject()
theFileName = QString("no file");
DataObject::DataObject(QString filename)
theFileName = filename;
//...
// Do file I/O stuff (slow) ...
这不是很现实,但可以作为一个简单的草图来说明我在下面遇到的问题。
当我尝试将 QtConcurrent::blockingMapped() 封装在一个额外的“datamodel.h”类中时会出现问题:
#include "dataobject.h"
class DataModel
public:
DataModel();
void runConcurrent();
DataObject load(const QString& fileList);
;
#include "datamodel.h"
#include <QtConcurrent/QtConcurrentMap>
#include <iostream>
DataModel::DataModel()
DataObject DataModel::load(const QString &file)
std::cout << "File I/O in thread = " << QThread::currentThread() << std::endl;
return DataObject anObject(file);
void DataModel::runConcurrent()
// Create a list of filenames:
int count = 5;
QList<QString> allFiles;
for (int i = 0; i < count; i++)
allFiles.append(QString("dummyFileName"));
QList<DataObject> allTheDataObjects = QtConcurrent::blockingMapped(allFiles, this->load);
std::cout << "# of objects = " << allTheDataObjects.size() << std::endl;
然后 main() 就变成了(注意我也把 load() 方法移到了 DataModel 类中):
#include <QList>
#include <iostream>
#include "dataobject.h"
#include "datamodel.h"
#include <QtConcurrent/QtConcurrentMap>
int main(int argc, char *argv[])
...
DataModel theModel;
theModel.runConcurrent();
...
但是现在出现编译错误:
datamodel.cpp: error: reference to non-static member function must be called:
QList<DataObject> allTheDataObjects = QtConcurrent::blockingMapped(allFiles, this->load);
我无法通过初始化 DataObject 或 DataModel 实例来修复编译器错误(以便可以看到非静态成员函数),并且不确定还可以尝试什么。
接下来我怀疑这可能是由于设置 QtConcurrent 参数时“函子”绑定的问题(我没有安装 boost,所以没有使用 boost::bind)所以我尝试了使用 C++ 11 的 Mat's suggestion lambdas 通过替换:
this->load
与:
[this](const QString& file)load(file);
给出代码:
QList<DataObject> allTheDataObjects = QtConcurrent::blockingMapped(allFiles,
[this](const QString& file)load(file););
现在我不再得到非静态成员错误,而是出现了一个新错误(指向上面的行):
datamodel.cpp: error: expected expression:
我真的在这个问题上陷入了困境,这可能是一个简单的错误,但我无法解决它。
有人可以帮忙吗?
【问题讨论】:
【参考方案1】:显然您不使用具有 lambda 表达式的 C++11。所以使用 STL 或 Boost 中的绑定或创建函数对象。
QList<DataObject> allTheDataObjects = QtConcurrent::blockingMapped(allFiles,
std::bind1st(std::mem_fun(&DataModel::load), this));
好的,以上解决方案不能与引用一起使用(知道错误)。定义函子(或使用 Boost::bind):
class LoadDataModel /*: public std::unary_function<QString, DataObject>*/
public:
LoadDataModel(DataModel *p) : d(p)
DataObject operator()(const QString &s) const
return d->load(s);
private:
DataModel *d;
QList<DataObject> allTheDataObjects = QtConcurrent::blockingMapped(allFiles, LoadDataModel(this));
【讨论】:
您的建议生效了吗?添加 #includethis
写在函数名之前,fileList
写在函数名之后。没有对象就不能调用这个函数。
谢谢,这是有道理的,但它在没有 DataModel 类的情况下运行良好似乎仍然很奇怪。【参考方案2】:
好的,开始工作了。
如果这可以使那些不想弄乱绑定或编写自己的“函子”的人受益(下面的方法更简单):
首先使用 datamodel.h 文件中的静态类型来实现“加载”功能:
static DataObject load(const QString& fileList);
这是因为可以调用 C++ 类的静态函数而无需实例化对象。
那么,在datamodel.cpp文件中,就是这么简单:
DataModel::load
给予:
QList<DataObject> allTheDataObjects =
QtConcurrent::blockingMapped(allFiles, DataModel::load);
然后代码按预期运行。
【讨论】:
以上是关于QtConcurrent 错误:对非静态成员的引用的主要内容,如果未能解决你的问题,请参考以下文章
Qt 如何在 QtConcurrent 中将指针绑定到非静态成员函数?
无法从 HibernateUtil 类型对非静态方法 getSessionFactory() 进行静态引用