Qt经典出错信息之undefined reference to `vtable for classn

来源:互联网 发布:json数据http协议 编辑:程序博客网 时间:2024/05/19 20:43

这个出错信息太常见了,用过Qt两个月以上的朋友基本上都能自己解决了,因为太经典了,可以给新手参考。出错信息一般类似:undefined reference to `vtable for classname MyWidget`,在执行make命令后出现。


出错原因是在定义类的时候为了能使用signals和slot,在类定义的后面加了Q_OBJECT引起。 因为Q_OBJECT是一个宏,在不同的类中展开是不同的代码,例如在mywidgeth.h中生成的:

public:template  inline void qt_check_for_QOBJECT_macro(const T &_q_argument) const {int i = qYouForgotTheQ_OBJECT_Macro(this, &_q_argument); i = i;}static const QMetaObject staticMetaObject;virtual const QMetaObject *metaObject() const;virtual void *qt_metacast(const char *);static inline QString tr(const char *s, const char *c = 0) {    return staticMetaObject.tr(s, c);}static inline QString trUtf8(const char *s, const char *c = 0){    return staticMetaObject.trUtf8(s, c);}static inline QString tr(const char *s, const char *c, int n) { return staticMetaObject.tr(s, c, n);}static inline QString trUtf8(const char *s, const char *c, int n) {return staticMetaObject.trUtf8(s, c, n);}virtual int qt_metacall(QMetaObject::Call, int, void **); private:

可以看到以上的代码声明了3个从父类继承的3个虚函数。本来这三个函数的实现应该是由moc_mywidget.cpp来完成。
而当前的错误正是因为Makefile里没有将moc_mywidget.cpp加入编译引起。


Makefile背后的原因是qmake,因为Qt的编译系统是通过qmake将.pro文件转换成Makefile文件。当qmake扫描.h代码时发现有Q_OBJECT这样字眼的代码时,会将一个用moc生成moc_xxx.cpp代码的依赖关系写到Makefile里。如果扫描时没有找到Q_OBJECT就不会生成额外的moc_xxx.cpp这样的文件。


出现最初一幕的原因是在执行qmake的时候.h代码里并没有O_OBJECT这样的代码。而执行make的时候.h里已经有Q_OBJECT了,解决的方法就是重新执行qmake,然后执行make.

——

shiroki:另外我再加一句, 还有一种可能性是写代码的人把所有的代码都写在了.cpp文件中。要知道moc工具只读.h文件,如果把Q_OBJECT宏放在cpp里moc是看不到的……所以大家写代码还是要遵守声明放.h实现放cpp的规矩比较好。