为什么我不能调用 QMetaObject::invokeMethod(&threadObj, &QThread::start, Qt::QueuedConnection)?
Why can't I call QMetaObject::invokeMethod(&threadObj, &QThread::start, Qt::QueuedConnection)?
我有一个控制台应用程序,在 main()
中有一个 QCoreApplication
运行 事件循环。
这里我有一个对象,它是 QThread 的派生对象,实现了 run()
来做一些测试。
我希望线程在启动我的应用程序时启动,所以我调用了
QMetaObject::invokeMethod(&threadObj, &QThread::start, Qt::QueuedConnection);
return qapp.exec();
在 main()
结束时。
这是我的问题:为什么这不能编译?
用 QThread::quit
做同样的事情很好,但 QThread::exit
不行。
我认为它与 start
和 exit
?`
的参数有关
编译器错误看起来像这样顺便说一句:
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
中实现自定义插槽。
我问这个是因为我很好奇为什么这不起作用,因为我认为语法很好。
看来我找到了答案。
正如我最初预期的那样,问题不在 Qt 中,而是在 C++ 中。
当使用函数指针进行间接函数调用时,只能调用参数列表为空的函数。 (喜欢QThread::quit(void)
)
当调用具有参数列表(包括默认参数)的函数时,它会隐式调用具有显式参数的函数。这在这里不起作用,因为函数指针中不能有参数。
正确的实现方式似乎是 lambda。
QMetaObject::invokeMethod(&threadObj, [&threadObj]() {threadObj.start(); }, Qt::QueuedConnection);
这样,你仍然可以在编译时检查语句的有效性。
鲍勃,你好
问题是 QThread::start
的参数的存在,虽然是默认的,并且 Qt 在 QMetaObject::invokeMethod
最重要的重载是用 const char *member
定义的方面被破坏了第二个参数。因此,使用这些重载之一,您可以直接使用它:
#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 几乎相同,但恕我直言,意图更明确。
我有一个控制台应用程序,在 main()
中有一个 QCoreApplication
运行 事件循环。
这里我有一个对象,它是 QThread 的派生对象,实现了 run()
来做一些测试。
我希望线程在启动我的应用程序时启动,所以我调用了
QMetaObject::invokeMethod(&threadObj, &QThread::start, Qt::QueuedConnection);
return qapp.exec();
在 main()
结束时。
这是我的问题:为什么这不能编译?
用 QThread::quit
做同样的事情很好,但 QThread::exit
不行。
我认为它与 start
和 exit
?`
编译器错误看起来像这样顺便说一句:
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
中实现自定义插槽。
我问这个是因为我很好奇为什么这不起作用,因为我认为语法很好。
看来我找到了答案。
正如我最初预期的那样,问题不在 Qt 中,而是在 C++ 中。
当使用函数指针进行间接函数调用时,只能调用参数列表为空的函数。 (喜欢QThread::quit(void)
)
当调用具有参数列表(包括默认参数)的函数时,它会隐式调用具有显式参数的函数。这在这里不起作用,因为函数指针中不能有参数。
正确的实现方式似乎是 lambda。
QMetaObject::invokeMethod(&threadObj, [&threadObj]() {threadObj.start(); }, Qt::QueuedConnection);
这样,你仍然可以在编译时检查语句的有效性。
鲍勃,你好
问题是 QThread::start
的参数的存在,虽然是默认的,并且 Qt 在 QMetaObject::invokeMethod
最重要的重载是用 const char *member
定义的方面被破坏了第二个参数。因此,使用这些重载之一,您可以直接使用它:
#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 几乎相同,但恕我直言,意图更明确。