Qt出現“undefined reference to vtable for”原因總結 (轉my gallery)

由於Qt本身實現的機制所限,我們在使用Qt製作某些軟件程序的時候,會遇到各種各樣這樣那樣的問題,而且很多是很難,或者根本找不到原因的,即使解決了問題,如果有人問你爲什麼,你只能回答--不知道;
今天我在這裏列舉的問題也是再編寫Qt程序時,總是遇到的問題,問題普遍,而答案卻不唯一,解釋這一個問題的說法很多,往往只適合某一種情況,因爲這個錯誤太籠統了,它就是-- “undefined reference to `vtablefor”可能你看着很熟悉,似乎在c++程序中也遇到過這個問題,你說對了,有時候這個錯誤,不只是qt的原因,還有你的c++程序的原因;

下面蒐集了網上的一些出現的現象,對應解決方法,原因,基本上我都驗證過,收錄於此,以做備份;

一:
預編譯器打開宏Q_OBJECT,聲明若干個由moc處理(implement)的成員函數。如果得到類似於“undefined referenceto vtable for LcdNumber”的編譯錯誤(if you get compiler errors along thelines of "undefined reference to vtable forLcdNumber"),你可能是忘記了執行moc,或者忘記了將moc輸出加入到link命令裏。

某一個類中如果加入Q_OBJECT後,則link時提示:undefined reference to vtable for "xxx::xxx".刪掉它則沒有任何問題.

解決:嘗試(1):把所有的obj文件和uic文件還有Makefile,Makefile.Debug,Makefile.Release和debug/release兩個文件夾都刪除,重新編譯.
仍然失敗.去trolltech的mail lists找到原因:因爲qmake生成Makefile的時候,這個類的頭文件中並沒有Q_OBJECT,所以在相應的Makefile裏面並沒有用mocxxx.h命令,最終導致鏈接失敗.重新運行qmake,問題解決.
在查找解決方法的時候,附帶發現一點:
qmake 不會處理.cpp文件裏的Q_OBJECT,所以,如果在.cpp文件中有它的話,也會產生undefined reference tovtable for "xxx::xxx". 這時,需要先用mocxxxx.cpp生成相應的moc文件,再包含到.cpp裏面去,才能解決這個問題.

這裏可以發現問題的出現是因爲沒有moc生成相應的moc文件,之後連接就出問題。
我找了好多源碼之類的問題,就是沒有找pro的錯誤,後來想到qt中moc我們是有make做的
qt的make編譯是根據Makefile來的,而Makefile是由pro文件來的。這纔想到了找pro文件的錯誤。
from: http://www.cublog.cn/u/16292/showart_136087.html

二:

undefined reference to vtable for "xxx::xxx"
今天碰到了這個問題,終於被我google到了:
http://www.cublog.cn/opera/showart.php?blogid=8650&id=49526
原 因:qmake不會處理.cpp文件裏的Q_OBJECT,所以,如果在.cpp文件中有它的話,也會產生undefined referenceto vtable for "xxx::xxx". 這時,需要先用mocxxxx.cpp生成相應的moc文件,再包含到.cpp裏面去,才能解決這個問題.
其他:
1.問題: QGLViewer中的函數不能正常link.解決: 翻看其源代碼,發現是因爲從源碼安裝libQGLViewer時,編譯用了Qt3,而我的程序中用Qt4 編譯.所以必須重新用Qt4編譯.但是,更改QTDIR環境變量爲Qt4後,重新編譯的話,qmake生成makefile時就提示出錯.進一步發現,是因爲雖然設了QTDIR爲Qt4,頭文件和庫文件都會使用Qt4,但是moc,uic等都是用的qt3版的,再把PATH環境變量改動後,一切ok.
2.問題:某一個類中如果加入Q_OBJECT後, 則link時提示:undefined reference to vtable for"xxx::xxx".刪掉它則沒有任何問題.解決:嘗試(1):把所有的obj文件和uic文件刪除,重新編譯.仍然失敗.去trolltech的mail lists找到原因:因爲qmake生成Makefile的時候,這個類的頭文件中並沒有Q_OBJECT,所以在相應的Makefile裏面並沒有用mocxxx.h命令,最終導致鏈接失敗.重新運行qmake,問題解決.在查找解決方法的時候,附帶發現一點:qmake不會處理.cpp文件裏的Q_OBJECT,所以,如果在.cpp文件中有它的話,也會產生undefined reference tovtable for "xxx::xxx". 這時,需要先用mocxxxx.cpp生成相應的moc文件,再包含到.cpp裏面去,才能解決這個問題.
3. 看Qt的reference發現: 可以connect(pObjA,SIGNAL(someSignalA()),pObjB,SIGNAL(someSignalB()));這樣pObjA發出的someSingalA會導致pObjB發出someSignalB,從而形成信號接力.

from:http://blog.donews.com/netexe/archive/2006/02/09/720544.aspx

三:
編譯報錯的部分是:


CODE:[Copy to clipboard]tmp/obj/release_shared/myplot.o(.text+0x194):myplot.cpp: undefined reference to
`vtable for MyPlot'
tmp/obj/release_shared/myplot.o(.text+0x19b):myplot.cpp: undefined reference to
`vtable for MyPlot'
tmp/obj/release_shared/myplot.o(.text+0x934):myplot.cpp: undefined reference to
`vtable for MyPlot'
tmp/obj/release_shared/myplot.o(.text+0x93b):myplot.cpp: undefined reference to
`vtable for MyPlot'
collect2: ld returned 1 exit status
你 MyPlot 是不是聲明瞭什麼 virtual 的 方法, 但在實現(cpp)文件裏沒有實現。
看了一下, 現在推測一下。 MyPlot 繼承了 QwtPlot, 現在報的這個錯, 應該是這個意思,
1. QwtPlot 裏含有 vritual 方法, 所以你的繼承類需要一個 virtual 的析構函數
2. QwtPlot 裏含有 純虛的方法, 你沒有繼承, 而這個可能性比較小


所以, 你可以:
在MyPlot裏聲明一下一個虛的析構函數
virtual ~MyPlot() {}

我們來看一個簡單些的例子吧:


CODE:[Copy to clipboard]#include <qapplication.h>
#include <qpushbutton.h>

class myWidget :public QWidget
{
Q_OBJECT
public:
       myWidget(QWidget *parent = 0);
public slots:
       void shutDown();
private:
        QPushButton *exit;
};

myWidget::myWidget(QWidget *parent):QWidget(parent)
{
                           setMinimumSize(120, 180);
                           setMaximumSize(120, 180);
                           exit = new QPushButton("ShutDown!",this);
                           connect(exit,SIGNAL(clicked()),this,SLOT(shutDown()));
}

void myWidget::shutDown()
{
     system("halt");
}

int main(int argc, char **argv)
{
    QApplication app(argc, argv);
    myWidget *w = new myWidget();
    w->show();
    app.exec();
}
還是報錯:


CODE:[Copy to clipboard]shut.o(.text+0x21): In function `myWidget::myWidget[not-in-charge](QWidget*, char const*)':
: undefined reference to `vtable for myWidget'
shut.o(.text+0x28): In function `myWidget::myWidget[not-in-charge](QWidget*, char const*)':
: undefined reference to `vtable for myWidget'
shut.o(.text+0x141): In function `myWidget::myWidget[in-charge](QWidget*, char const*)':
: undefined reference to `vtable for myWidget'
shut.o(.text+0x148): In function `myWidget::myWidget[in-charge](QWidget*, char const*)':
: undefined reference to `vtable for myWidget'
collect2: ld returned 1 exit status
這是我從l搜索引擎上搜到的例子,從代碼中好像看不到明顯的錯誤吧
我自己試了一下編譯也是出錯

剛纔那個簡單的例子的原因可能是這樣的:


QUOTE:
2.問題:某一個類中如果加入Q_OBJECT後,則link時提示:undefined reference to vtable for "xxx::xxx".刪掉它則沒有任何問題.


解決:嘗試(1):把所有的obj文件和uic文件刪除,重新編譯.仍然失敗.


去trolltech的mail lists找到原因: 因爲qmake生成Makefile的時候,這個類的頭文件中並沒有Q_OBJECT,所以在相應的Makefile裏面並沒有用moc xxx.h命令,最終導致鏈接失敗.重新運行qmake,問題解決.


在查找解決方法的時候,附帶發現一點:


qmake不會處理.cpp文件裏的Q_OBJECT,所以,如果在.cpp文件中有它的話,也會產生undefined reference tovtable for "xxx::xxx". 這時,需要先用mocxxxx.cpp生成相應的moc文件,再包含到.cpp裏面去,才能解決這個問題.
知道你的問題了, 上面的例子不好, 因爲你這個把main和類放在一起了。 如果分開, 可能就沒問題, 包括 h和 cpp 分開。

要解決上面的問題, 在你main.cpp 最後加一行
#include "main.moc"

然後把除了 main.cpp 的其它文件都刪了。重新來, 沒問題的。

所以, 我估計你前面提到的問題也是沒有鏈接 moc 文件。 你在你的 myplot.cpp 文件最後加一行: #include "myplot.moc" 試試看。


另外: 你main 沒有返回值, 編譯會警告, 而且程序最後一行不是隻含有回車, 也會警告。


這是一個論壇貼,完整討論請看:http://www.myswear.net/forum/viewthread.php?tid=5177&extra=&page=1


四:

Qt自己也有對這個的解釋:
http://www.qtopia.org.cn/doc/4.1/signalsandslots.html

差不多了,我今天遇到了一個更詭異的,幾個文件單獨編譯都沒有問題,就是鏈接出現錯誤,最後信手刪掉報錯文件中的某個宏定義(此宏定義是定義是否只是用qt的一個定義),然後,就ok了,你說怪不怪,我現在也沒想通原因;faint。。。Qt還真是折磨人。。。

本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/baymoon/archive/2006/11/23/1409167.aspx

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