为什么我不能调用QMetaObject :: invokeMethod(&threadObj,&QThread :: start,Qt :: QueuedConnection)?

时间:2019-12-12 12:39:33

标签: c++ qt qthread

我有一个控制台应用程序,其中一个QCoreApplicationmain()中运行事件循环。 在这里,我有一个对象,它是QThread的派生对象,实现了run()以进行一些测试。 我希望线程在启动应用程序时启动,所以我调用了

QMetaObject::invokeMethod(&threadObj, &QThread::start, Qt::QueuedConnection);
return qapp.exec();

main()的结尾。

这是我的问题:为什么不编译?

QThread::quit进行相同的操作可以正常工作,而QThread::exit则不能。 我认为它与startexit的参数有关?

编译器错误如下所示:

d:\dev\project\project\main.cpp(49): error C2665: 'QMetaObject::invokeMethod': none of the 4 overloads could convert all the argument types
1>x:\hmi_qt5\qt\msvc2017_x86\debug\include\qtcore\qobjectdefs.h(448): note: could be 'bool QMetaObject::invokeMethod(QObject *,const char *,QGenericArgument,QGenericArgument,QGenericArgument,QGenericArgument,QGenericArgument,QGenericArgument,QGenericArgument,QGenericArgument,QGenericArgument,QGenericArgument)' (compiling source file main.cpp)
1>x:\hmi_qt5\qt\msvc2017_x86\debug\include\qtcore\qobjectdefs.h(431): note: or       'bool QMetaObject::invokeMethod(QObject *,const char *,Qt::ConnectionType,QGenericArgument,QGenericArgument,QGenericArgument,QGenericArgument,QGenericArgument,QGenericArgument,QGenericArgument,QGenericArgument,QGenericArgument,QGenericArgument)' (compiling source file main.cpp)
1>x:\hmi_qt5\qt\msvc2017_x86\debug\include\qtcore\qobjectdefs.h(414): note: or       'bool QMetaObject::invokeMethod(QObject *,const char *,QGenericReturnArgument,QGenericArgument,QGenericArgument,QGenericArgument,QGenericArgument,QGenericArgument,QGenericArgument,QGenericArgument,QGenericArgument,QGenericArgument,QGenericArgument)' (compiling source file main.cpp)
1>d:\dev\project\project\main.cpp(49): note: while trying to match the argument list '(threadObj*, void (__thiscall QThread::* )(QThread::Priority), Qt::ConnectionType)'

预先感谢

鲍勃

PS: 通过使用函子或在threadObj中实现自定义插槽,我确实有解决方法。 我问这个问题是因为我很好奇为什么这样做不起作用,因为我认为语法很好。

2 个答案:

答案 0 :(得分:1)

问题是存在QThread::start参数(尽管默认),并且在QMetaObject::invokeMethod最重要的重载被定义为const char *member作为第二个方面,Qt被破坏了。参数。因此,使用这些重载之一可以直接使用它:

#include <functional>

#include <QtWidgets/QApplication>
#include <QtWidgets/QtWidgets>
#include <QtWidgets/QMainWindow>

#include <QThread>

int main(int argc, char *argv[]) {
    QThread threadObj;
    QMetaObject::invokeMethod(&threadObj, "start", Qt::QueuedConnection);

    QApplication this_application(argc, argv);
    return this_application.exec();
}

另一种解决方法是

QMetaObject::invokeMethod(&threadObj, std::bind(&QThread::start,std::ref(threadObj),QThread::InheritPriority), Qt::QueuedConnection);

与lambda几乎相同,但是恕我直言,意图更明确。

答案 1 :(得分:0)

所以看来我找到了答案。 正如我最初预期的那样,问题不在于Qt内,而是C ++内。 使用函数指针进行间接函数调用时,只能调用参数列表为空的函数。 (如QThread::quit(void)) 当调用具有参数列表(包括默认参数)的函数时,它将使用显式参数隐式调用该函数。这在这里不起作用,因为在functoin指针中不能有参数。

实现此目标的正确方法似乎是lambda。

QMetaObject::invokeMethod(&threadObj, [&threadObj]() {threadObj.start(); }, Qt::QueuedConnection);

这样,您仍然可以在编译时检查语句的有效性。

问候,鲍勃