Qt 如何在 QtConcurrent 中将指针绑定到非静态成员函数?
Posted
技术标签:
【中文标题】Qt 如何在 QtConcurrent 中将指针绑定到非静态成员函数?【英文标题】:How does Qt bind pointers-to-non-static-member-functions in QtConcurrent? 【发布时间】:2011-11-16 17:25:32 【问题描述】:来自QtConcurrent documentation:
QByteArray bytearray = "hello world";
QFuture<QList<QByteArray> > future = QtConcurrent::run(bytearray, &QByteArray::split), ',');
...
QList<QByteArray> result = future.result();
上面的代码 sn-p 似乎以类似于std::tr1::bind
的方式绑定一个函数(std::bind
for > C++11)。也就是说,它采用非静态成员函数 (QByteArray::split()
) 并(稍后)在它所属的对象的特定实例上调用它(我们提供为 bytearray
)。
Qt 是如何做到这一点的?是在幕后使用std::tr1::bind
还是boost::bind
?
The documentation 也指代您使用 std::tr1
或 boost
的情况,但我不完全理解 绑定函数 在这种情况下的含义。上述情况实际上是否与您可能使用tr1
或boost
的其他情况不同/更专业/更简单?
我试图通过源头找到自己的方式,但很快就迷路了!
【问题讨论】:
【参考方案1】:我将尝试一个自我回答,因为现有的答案(非常感谢@Mike Brown 和@skyhisi)奠定了基础,但不解决这个具体案例......
来源:
QtConcurrent::run(...) :
template <typename T, typename Class>
QFuture<T> run(const Class &object, T (Class::*fn)())
return (new QT_TYPENAME SelectStoredMemberFunctionCall0<T, Class>::type(fn, object))->start();
SelectStoredMemberFunctionCall0:
template <typename T, typename Class>
struct SelectStoredMemberFunctionCall0
typedef typename SelectSpecialization<T>::template
Type<StoredMemberFunctionCall0 <T, Class>,
VoidStoredMemberFunctionCall0<T, Class> >::type type;
;
VoidStoredMemberFunctionCall0:
template <typename T, typename Class>
class VoidStoredMemberFunctionCall0 : public RunFunctionTask<T>
public:
VoidStoredMemberFunctionCall0(T (Class::*_fn)() , const Class &_object)
: fn(_fn), object(_object)
void runFunctor()
(object.*fn)();
private:
T (Class::*fn)();
Class object;
;
鉴于上述情况,我可以看到 Qt 在 normal way 中存储了一个指向成员函数的指针,但是通过将其装饰在模板中,否则会被忽视,从而产生了泛型的错觉。
VoidStoredMemberFunctionCall0::object
的类型以及VoidStoredMemberFunctionCall0::fn
的签名都在上面传递给QtConcurrent::run
的参数中指定。
说实话,我什至不知道这种“隐式”模板化是可能的。有人可以推荐进一步阅读吗?
【讨论】:
我发现The C++ Programming Language 这本书对于理解 C++ 非常有用。 C++ FAQ Templates 页面对模板的许多方面也有很好的解释。【参考方案2】:C++ FAQ 很好地解释了Pointers to member functions 并解释了陷阱。
在某些时候会有类似的一行:
ret_val = obj_ptr->*func_ptr(param);
但它会被封装在模板中以允许传递任何对象类型和参数类型,并且其中也会混杂线程调度。
【讨论】:
【参考方案3】:您正在传递函数指针和声明函数的类的实例。调用它就像从对象中取消引用函数指针一样简单。 This *** Question 给出答案
【讨论】:
我知道QtConcurrent::run
必须使用指向成员函数的指针,我只是不明白它如何在函数返回类型、参数和对象时存储指针/调用函数其中它的成员不是在QtConcurrent
中硬编码,而是从提供给run(...)
的参数中提取。以上是关于Qt 如何在 QtConcurrent 中将指针绑定到非静态成员函数?的主要内容,如果未能解决你的问题,请参考以下文章
Qt文档阅读笔记-QtConcurrent Progress Dialog Example解析
Qt多线程:QtConcurrent + QFuture + QFutureWatcher