Qt5的一些古怪问题
开发环境
Qt5.12, Ubuntu 20.04 Linux 4.17
编译QObject时出现undefined reference to ‘vtable for XXX’
2021-01-26
现象描述:
Qt5编译时出现:
undefined reference to ‘vtable for XXX’
问题复现
- 新建一个C++标准的Class,并且可以正常编译通过
class MyClass { MyClass(); }
- 此时,突然想让这个Class继承QObject类,于是手动添加了QObject相关的标识
#include <QObject> class MyClass : public QObject { Q_OBJECT MyClass(); }
- 再次编译就出现 undefined reference to ‘vtable for XXX’ 的错误
原因分析
后期改动添加的QObject类,编译器是无法生成对应的moc_XXX.cpp文件的,所以无法链接
解决方案
- 右键Remove移除Class,切忌不要把文件删除咯,只是移除工程而已
- 再次添加文件,选择已有代码“Add Existing Files …”
- 重新编译工程即可
QThread中的信号Signal与槽Slot建立连接失败,不起作用
2021-02-02
现象描述:
Qt5建立了QTimer,connect成功,编译正确,但timeout信号却无法触发槽Slot函数
问题复现
- 建立一个QTimer timer,一个slot SlotUpdateTimer()
class MyClass { public: MyClass(); void Init(); void Run(); private: Qtimer *timer_; public slots: void SlotUpdateTimer(); ... }
- 初始化QTimer并建立connect连接
void MyClass::Init() { timer_ = new QTimer; connect(timer_, &QTimer::timeout, this, &MyClass::SlotUpdateTimer); } void MyClass::Run() { timer_->start(1000); } void MyClass::SlotUpdateTimer() { printf("timeout"); timer_->start(1000); } ...
- 建立线程QThread并运行QTimer
main() { QThread thread; MyClass my; my.moveToThread(&thread); my.Init(); my.start(); my.Run(); ... }
- 运行代码后发现,并没有printf输出
原因分析
main()函数所在线程与MyClass my所在线程不一致所造成
QTimer的初始化my.Init()位于线程A,但timer的调用在线程B
解决方案
- 需要将QTimer初始化过程与其调用方法放于同一线程内
- 增加一个信号Signal和槽Slot函数,用于触发QTimer初始化
class MyClass {
...
signals:
void SignalInitTimer();
public slots:
void SlotInitTimer();
...
}
- 实现函数
void MyClass::Init() {
connect(this, &MyClass::SignalInitTimer, this, &MyClass::SlotInitTimer);
}
void MyClass::SlotInitTimer() {
timer_ = new QTimer;
connect(timer_, &QTimer::timeout, this, &MyClass::SlotUpdateTimer);
timer_->start(1000);
}
void MyClass::Run() {
emit SignalInitTimer();
}
- 运行后可以得到printf输出
// end donion.yang