Qt經典出錯信息之undefined reference to `vtable for classn

這個出錯信息太常見了,用過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的規矩比較好。



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章