2011-05-02 432 views
19

下面的例子此鏈接:http://developer.kde.org/documentation/books/kde-2.0-development/ch03lev1sec3.html的Qt:信號和槽錯誤:未定義的參考`虛函數表爲

#include <QObject> 
#include <QPushButton> 
#include <iostream> 
using namespace std; 

class MyWindow : public QWidget 
{ 
    Q_OBJECT // Enable slots and signals 
    public: 
     MyWindow(); 
    private slots: 
     void slotButton1(); 
     void slotButton2(); 
     void slotButtons(); 
    private: 
     QPushButton *button1; 
     QPushButton *button2; 
}; 

MyWindow :: MyWindow() : QWidget() 
{ 
    // Create button1 and connect button1->clicked() to this->slotButton1() 
    button1 = new QPushButton("Button1", this); 
    button1->setGeometry(10,10,100,40); 
    button1->show(); 
    connect(button1, SIGNAL(clicked()), this, SLOT(slotButton1())); 

    // Create button2 and connect button2->clicked() to this->slotButton2() 
    button2 = new QPushButton("Button2", this); 
    button2->setGeometry(110,10,100,40); 
    button2->show(); 
    connect(button2, SIGNAL(clicked()), this, SLOT(slotButton2())); 

    // When any button is clicked, call this->slotButtons() 
    connect(button1, SIGNAL(clicked()), this, SLOT(slotButtons())); 
    connect(button2, SIGNAL(clicked()), this, SLOT(slotButtons())); 
} 

// This slot is called when button1 is clicked. 
void MyWindow::slotButton1() 
{ 
    cout << "Button1 was clicked" << endl; 
} 

// This slot is called when button2 is clicked 
void MyWindow::slotButton2() 
{ 
    cout << "Button2 was clicked" << endl; 
} 

// This slot is called when any of the buttons were clicked 
void MyWindow::slotButtons() 
{ 
    cout << "A button was clicked" << endl; 
} 

int main() 
{ 
    MyWindow a; 
} 

結果:

[13:14:34 Mon May 02] ~/junkPrograms/src/nonsense $make 
g++ -c -m64 -pipe -O2 -Wall -W -D_REENTRANT -DQT_NO_DEBUG -DQT_GUI_LIB -DQT_CORE_LIB -DQT_SHARED -I/opt/qtsdk-2010.05/qt/mkspecs/linux-g++-64 -I. -I/opt/qtsdk-2010.05/qt/include/QtCore -I/opt/qtsdk-2010.05/qt/include/QtGui -I/opt/qtsdk-2010.05/qt/include -I. -I. -o signalsSlots.o signalsSlots.cpp 
g++ -m64 -Wl,-O1 -Wl,-rpath,/opt/qtsdk-2010.05/qt/lib -o nonsense signalsSlots.o -L/opt/qtsdk-2010.05/qt/lib -lQtGui -L/opt/qtsdk-2010.05/qt/lib -L/usr/X11R6/lib64 -lQtCore -lpthread 
signalsSlots.o: In function `MyWindow::MyWindow()': 
signalsSlots.cpp:(.text+0x1a2): undefined reference to `vtable for MyWindow' 
signalsSlots.cpp:(.text+0x1aa): undefined reference to `vtable for MyWindow' 
signalsSlots.o: In function `MyWindow::MyWindow()': 
signalsSlots.cpp:(.text+0x3e2): undefined reference to `vtable for MyWindow' 
signalsSlots.cpp:(.text+0x3ea): undefined reference to `vtable for MyWindow' 
signalsSlots.o: In function `main': 
signalsSlots.cpp:(.text+0x614): undefined reference to `vtable for MyWindow' 
signalsSlots.o:signalsSlots.cpp:(.text+0x61d): more undefined references to `vtable for MyWindow' follow 
collect2: ld returned 1 exit status 
make: *** [nonsense] Error 1 

虛函數表是虛函數,據我所知,有什麼錯誤的原因在這裏?

+0

我不明白是什麼問題,但我想指出你正在使用的教程是相當過時的。我建議你看看Qt 4.7文檔中的教程。 – ypnos 2011-05-02 08:11:18

+0

@ypnos謝謝,但嘖4。7不顯示任何「正在運行」的例子,我可以只是粘貼和運行:( – 2011-05-02 08:28:39

+0

可能重複的[Qt moc與頭文件內的實現?](http://stackoverflow.com/questions/3001615/qt- moc-with-implementation-inside-of-header-files) – 2017-01-05 17:27:04

回答

36

看起來moc不會爲您的QObject生成代碼,因爲您在.cpp文件中聲明它。要解決這個問題最簡單的方法是到MyWindow聲明移到頭,和頭添加到HEADERS列表,在的.pro文件:

HEADERS += yourheader.h 

然後重新運行qmake

(請注意,你看看KDE 2.0本書是大大落伍)

+0

感謝您的迴應,但是有沒有辦法通過它來保存.cpp文件中的聲明和定義? – 2011-05-02 08:16:29

+0

嘗試使用HEADERS + = your.cpp。一般來說,儘管可能,我發現QObject聲明非常痛苦,我寧願擁有它們(私有)頭文件。對於所有的構建系統都可以,無論是qmake,cmake,... – 2011-05-02 08:21:34

+0

再次感謝我分離.h, .cpp和main:mad:它解決了錯誤,我還沒有研究有關moc文件的細節。 – 2011-05-02 08:27:37

1

只是改變你的Main()方法如下:

#include <QtGui/QApplication> 

int main(int argc, char *argv[]) 
{ 
    QApplication a(argc, argv); 
    MyWindow w; 

    w.show(); 

    return a.exec(); 
} 
1

基於略高於andref評論,當一切都在一個CPP文件中像stuff.cpp,你需要在文件的最後添加:

#include "moc_stuff.cpp" 

(這是使用Qt 4.7.0)

+0

使用Qt 4.8,這不適合我。我必須去做所提到的意見。 – Tshepang 2012-10-24 07:48:16

22

也許爲時已晚,但...有同樣的問題,並爭取一段時間,以找到它來自何處。

右鍵單擊您的項目並選擇「運行qmake」以獲得MOC類的新版本。它通常不會自動運行...

商務部編譯器生成的存根和moc_xxxx.cpp調用,並生成虛函數表的東西

+0

我不使用qtcreator。在我問這裏之前,我多次運行qmake。它沒有幫助。 – 2012-12-30 02:20:00

+0

@AnishaKaul同樣。爲我運行'qmake'不能解決任何問題。如果我運行'qmake --project',那麼它會重新生成'.pro',我可以編譯,但是這樣可以解決人們對'.pro'所做的所有更改,這非常糟糕。 – 2013-05-03 15:36:25

+2

1 ++這個修復我的問題 – Ivan 2013-09-25 20:36:38

0

此問題可能由以下一些原因造成的。我偶爾偶爾偶然發現了它們。


您的類標題可能缺少Q_OBJECT宏。如其他答案所述,將宏添加到標題中。

class MyWidg : public QWidget 
{ 
    Q_OBJECT 

你的類頭可能不是由商務部來解析。將頭文件添加到.pro(或.pri)項目文件的HEADERS定義中。

HEADERS += file.h 

如果以上都不是真實的,那麼你可能需要再次運行QMAKE確保商務部再次解析頭,以防萬一在頭部添加了Q_OBJECT宏QMAKE爲後跑。再次運行qmake。