2012-12-23 172 views
29

我是一個初學者Qt編程和使用codeblocks我的編程。我創建了3個文件communicate.h,commmunicate.cpp和main.cpp中,如下所示:Qt未定義的引用vtable

communicate.h

#ifndef COMMUNICATE_H 
    #define COMMUNICATE_H 

    #include <QWidget> 
    #include <QApplication> 
    #include <QPushButton> 
    #include <QLabel> 

    class Communicate : public QWidget 
    { 
     Q_OBJECT 

     public: 
     Communicate(QWidget *parent = 0); 


     private slots: 
     void OnPlus(); 
     void OnMinus(); 

     private: 
     QLabel *label; 

    }; 

    #endif 

communicate.cpp

#include "communicate.h" 

Communicate::Communicate(QWidget *parent) 
    : QWidget(parent) 
{ 
    QPushButton *plus = new QPushButton("+", this); 
    plus->setGeometry(50, 40, 75, 30); 

    QPushButton *minus = new QPushButton("-", this); 
    minus->setGeometry(50, 100, 75, 30); 

    label = new QLabel("0", this); 
    label->setGeometry(190, 80, 20, 30); 

    connect(plus, SIGNAL(clicked()), this, SLOT(OnPlus())); 
    connect(minus, SIGNAL(clicked()), this, SLOT(OnMinus())); 
} 

void Communicate::OnPlus() 
{ 
    int val = label->text().toInt(); 
    val++; 
    label->setText(QString::number(val)); 
} 

void Communicate::OnMinus() 
{ 
    int val = label->text().toInt(); 
    val--; 
    label->setText(QString::number(val)); 
} 

的main.cpp

#include "communicate.h" 

int main(int argc, char *argv[]) 
{ 
    QApplication app(argc, argv); 

    Communicate window; 

    window.setWindowTitle("Communicate"); 
    window.show(); 

    return app.exec(); 
} 

及其顯示錯誤如下:

obj\Debug\main.o(.text$_ZN11CommunicateD1Ev[Communicate::~Communicate()]+0xb)||In function `ZN7QStringC1EPKc':| 
C:\Qt\4.4.3\include\QtCore\..\..\src\corelib\arch\qatomic_windows.h||undefined reference to `vtable for Communicate'| 
obj\Debug\main.o(.text$_ZN11CommunicateD1Ev[Communicate::~Communicate()]+0x17):C:\Qt\4.4.3\include\QtCore\..\..\src\corelib\arch\qatomic_windows.h||undefined reference to `vtable for Communicate'| 
obj\Debug\communicate.o(.text+0x172)||In function `ZN11CommunicateC2EP7QWidget':| 
E:\Project\cam2\communicate.cpp|5|undefined reference to `vtable for Communicate'| 
obj\Debug\communicate.o(.text+0x17e):E:\Project\cam2\communicate.cpp|5|undefined reference to `vtable for Communicate'| 
obj\Debug\communicate.o(.text+0x63a)||In function `ZN11CommunicateC1EP7QWidget':| 
E:\Project\cam2\communicate.cpp|5|undefined reference to `vtable for Communicate'| 
obj\Debug\communicate.o(.text+0x646):E:\Project\cam2\communicate.cpp|5|more undefined references to `vtable for Communicate' follow| 
||=== Build finished: 6 errors, 0 warnings ===| 

傢伙請幫助...不能看着辦吧......

+2

請確保您的項目文件(.pro)包含在頭文件中的communications.h文件 – Zeks

+0

這是一個重複的,不是太本地化的 –

+4

我發現的最佳答案,那就是在這裏沒有提到的是重新運行qmake:http ://stackoverflow.com/a/3650758/258418 – ted

回答

17

這是個微妙的問題(可能部分至少一個編譯器錯誤),其我以前見過。由於QWidget具有虛擬析構函數,因此編譯器需要您的類的虛表。但是你的班級沒有任何虛擬功能,所以它沒有爲Communicate班級建立一個虛擬功能。

給你的班級增加一個virtual ~Communicate() {};,一切都會好的。

是的,我花了一些時間來弄清楚這一點!

+7

你是不正確的。我只是測試了這個類:class Test:public QObject {Q_OBJECT}並且這個編譯很好,假設頭文件駐留在.pro中。當我評論它時 - 我得到了undetablede的引用vtable – Zeks

+0

好吧,我已經看到了這個問題一個不同的設置,其中QT根本沒有涉及,並且問題是由於沒有聲明析構函數而導致的。因此,MOC可能正在「修復」這類事情? –

+0

如果添加通信,代碼編譯得很好。h在HEADERS部分中。 – Kikohs

12

MOC(元對象編譯器)需要知道你的communicate.h的(以及任何其他Q_OBJECT'ed類)來完成其工作。除非你把它們放入下頭部分.pro文件 - 你會得到這個「未定義的引用」

+0

我在Windows 7中使用代碼塊。我找不到任何.pro文件與項目目錄...可以更具體的請嗎? –

+0

@Zeks是的你說得對,Qt也需要知道自定義標題 – jondinham

18

快速選項來解決問題是去除Q_OBJECT宏,這將讓你編譯和測試應用程序, 但是,並非正確的選擇,如果您打算每天與CB上的QT一起工作,則必須配置您的環境。

我個人更喜歡的一種選擇是創建一個自定義的makefile和一個文件。 「親」的應用程序,它很容易在其他環境中運輸爲「QtCreator」「NetBeansIDE」等。

我會盡快解釋要遵循的步驟。如果你已經安裝了QtCreator,應該得到QtCreator文件自己生成的支持,並且有一點經驗可以建立你自己的文件。

這個例子只允許你在「目標版本」編譯並運行這些文件後,你將不得不定製你的工作環境

  • 創建文件:的Makefile


####### Compiler, tools and options 

PROJECT_NAME = Communicate 
QT_INCLUDE = /usr/local/QtSDK/Desktop/Qt/4.8.1/gcc/include/ 
QT_MKSPECS = /usr/local/QtSDK/Desktop/Qt/4.8.1/gcc/mkspecs/ 
QT_LIB  = /usr/local/QtSDK/Desktop/Qt/4.8.1/gcc/lib 
QT_QMAKE  = /usr/local/QtSDK/Desktop/Qt/4.8.1/gcc/bin/ 
CC   = gcc 
CXX   = g++ 
DEFINES  = -DQT_NO_DEBUG -DQT_GUI_LIB -DQT_CORE_LIB -DQT_SHARED 
CFLAGS  = -pipe -O2 -Wall -W -D_REENTRANT $(DEFINES) 
CXXFLAGS  = -pipe -O2 -Wall -W -D_REENTRANT $(DEFINES) 
INCPATH  = -I$(QT_MKSPECS)linux-g++ -I../$(PROJECT_NAME) -I$(QT_INCLUDE)QtCore -I$(QT_INCLUDE)QtGui -I/usr/local/QtSDK/Desktop/Qt/4.8.1/gcc/include -I. -I../$(PROJECT_NAME) -I. 
LINK   = g++ 
LFLAGS  = -Wl,-O1 -Wl,-rpath,$(QT_LIB) 
LIBS   = $(SUBLIBS) -L$(QT_LIB) -lQtGui -L$(QT_LIB) -L/usr/X11R6/lib -lQtCore -lpthread 
AR   = ar cqs 
RANLIB  = 
QMAKE   = $(QT_QMAKE)qmake 
TAR   = tar -cf 
COMPRESS  = gzip -9f 
COPY   = cp -f 
SED   = sed 
COPY_FILE  = $(COPY) 
COPY_DIR  = $(COPY) -r 
STRIP   = strip 
INSTALL_FILE = install -m 644 -p 
INSTALL_DIR = $(COPY_DIR) 
INSTALL_PROGRAM = install -m 755 -p 
DEL_FILE  = rm -f 
SYMLINK  = ln -f -s 
DEL_DIR  = rmdir 
MOVE   = mv -f 
CHK_DIR_EXISTS= test -d 
MKDIR   = mkdir -p 

####### Output directory 

OBJECTS_DIR = ./Release 

####### Files 

SOURCES  = ../$(PROJECT_NAME)/main.cpp \ 
     ../$(PROJECT_NAME)/communicate.cpp moc_communicate.cpp 
OBJECTS  = main.o \ 
     communicate.o \ 
     moc_communicate.o 
DIST   = $(QT_MKSPECS)common/unix.conf \ 
     $(QT_MKSPECS)common/linux.conf \ 
     $(QT_MKSPECS)common/gcc-base.conf \ 
     $(QT_MKSPECS)common/gcc-base-unix.conf \ 
     $(QT_MKSPECS)common/g++-base.conf \ 
     $(QT_MKSPECS)common/g++-unix.conf \ 
     $(QT_MKSPECS)qconfig.pri \ 
     $(QT_MKSPECS)modules/qt_webkit_version.pri \ 
     $(QT_MKSPECS)features/qt_functions.prf \ 
     $(QT_MKSPECS)features/qt_config.prf \ 
     $(QT_MKSPECS)features/exclusive_builds.prf \ 
     $(QT_MKSPECS)features/default_pre.prf \ 
     $(QT_MKSPECS)features/release.prf \ 
     $(QT_MKSPECS)features/default_post.prf \ 
     $(QT_MKSPECS)features/unix/gdb_dwarf_index.prf \ 
     $(QT_MKSPECS)features/warn_on.prf \ 
     $(QT_MKSPECS)features/qt.prf \ 
     $(QT_MKSPECS)features/unix/thread.prf \ 
     $(QT_MKSPECS)features/moc.prf \ 
     $(QT_MKSPECS)features/resources.prf \ 
     $(QT_MKSPECS)features/uic.prf \ 
     $(QT_MKSPECS)features/yacc.prf \ 
     $(QT_MKSPECS)features/lex.prf \ 
     $(QT_MKSPECS)features/include_source_dir.prf \ 
     ../$(PROJECT_NAME)/$(PROJECT_NAME).pro 
QMAKE_TARGET = $(PROJECT_NAME) Release 
DESTDIR  = $(OBJECTS_DIR) 
TARGET  = $(PROJECT_NAME) 

first: all 
####### Implicit rules 

.SUFFIXES: .o .c .cpp .cc .cxx .C 

.cpp.o: 
    $(CXX) -c $(CXXFLAGS) $(INCPATH) -o "[email protected]" "$<" 

.cc.o: 
    $(CXX) -c $(CXXFLAGS) $(INCPATH) -o "[email protected]" "$<" 

.cxx.o: 
    $(CXX) -c $(CXXFLAGS) $(INCPATH) -o "[email protected]" "$<" 

.C.o: 
    $(CXX) -c $(CXXFLAGS) $(INCPATH) -o "[email protected]" "$<" 

.c.o: 
    $(CC) -c $(CFLAGS) $(INCPATH) -o "[email protected]" "$<" 

####### Build rules 

all: Makefile $(TARGET) 

$(TARGET): $(OBJECTS) 
    $(LINK) $(LFLAGS) -o $(TARGET) $(OBJECTS) $(OBJCOMP) $(LIBS) 

Makefile: ../$(PROJECT_NAME)/$(PROJECT_NAME).pro $(QT_MKSPECS)linux-g++/qmake.conf $(QT_MKSPECS)common/unix.conf \ 
     $(QT_MKSPECS)common/linux.conf \ 
     $(QT_MKSPECS)common/gcc-base.conf \ 
     $(QT_MKSPECS)common/gcc-base-unix.conf \ 
     $(QT_MKSPECS)common/g++-base.conf \ 
     $(QT_MKSPECS)common/g++-unix.conf \ 
     $(QT_MKSPECS)qconfig.pri \ 
     $(QT_MKSPECS)modules/qt_webkit_version.pri \ 
     $(QT_MKSPECS)features/qt_functions.prf \ 
     $(QT_MKSPECS)features/qt_config.prf \ 
     $(QT_MKSPECS)features/exclusive_builds.prf \ 
     $(QT_MKSPECS)features/default_pre.prf \ 
     $(QT_MKSPECS)features/release.prf \ 
     $(QT_MKSPECS)features/default_post.prf \ 
     $(QT_MKSPECS)features/unix/gdb_dwarf_index.prf \ 
     $(QT_MKSPECS)features/warn_on.prf \ 
     $(QT_MKSPECS)features/qt.prf \ 
     $(QT_MKSPECS)features/unix/thread.prf \ 
     $(QT_MKSPECS)features/moc.prf \ 
     $(QT_MKSPECS)features/resources.prf \ 
     $(QT_MKSPECS)features/uic.prf \ 
     $(QT_MKSPECS)features/yacc.prf \ 
     $(QT_MKSPECS)features/lex.prf \ 
     $(QT_MKSPECS)features/include_source_dir.prf \ 
     $(QT_LIB)/libQtGui.prl \ 
     $(QT_LIB)/libQtCore.prl 
    $(QMAKE) -spec $(QT_MKSPECS)linux-g++ -o Makefile ../$(PROJECT_NAME)/$(PROJECT_NAME).pro 
$(QT_MKSPECS)common/unix.conf: 
$(QT_MKSPECS)common/linux.conf: 
$(QT_MKSPECS)common/gcc-base.conf: 
$(QT_MKSPECS)common/gcc-base-unix.conf: 
$(QT_MKSPECS)common/g++-base.conf: 
$(QT_MKSPECS)common/g++-unix.conf: 
$(QT_MKSPECS)qconfig.pri: 
$(QT_MKSPECS)modules/qt_webkit_version.pri: 
$(QT_MKSPECS)features/qt_functions.prf: 
$(QT_MKSPECS)features/qt_config.prf: 
$(QT_MKSPECS)features/exclusive_builds.prf: 
$(QT_MKSPECS)features/default_pre.prf: 
$(QT_MKSPECS)features/release.prf: 
$(QT_MKSPECS)features/default_post.prf: 
$(QT_MKSPECS)features/unix/gdb_dwarf_index.prf: 
$(QT_MKSPECS)features/warn_on.prf: 
$(QT_MKSPECS)features/qt.prf: 
$(QT_MKSPECS)features/unix/thread.prf: 
$(QT_MKSPECS)features/moc.prf: 
$(QT_MKSPECS)features/resources.prf: 
$(QT_MKSPECS)features/uic.prf: 
$(QT_MKSPECS)features/yacc.prf: 
$(QT_MKSPECS)features/lex.prf: 
$(QT_MKSPECS)features/include_source_dir.prf: 
$(QT_LIB)/libQtGui.prl: 
$(QT_LIB)/libQtCore.prl: 
qmake: FORCE 
    @$(QMAKE) -spec $(QT_MKSPECS)linux-g++ -o Makefile ../$(PROJECT_NAME)/$(PROJECT_NAME).pro 

dist: 
    @$(CHK_DIR_EXISTS) .tmp/$(PROJECT_NAME)1.0.0 || $(MKDIR) .tmp/$(PROJECT_NAME)1.0.0 
    $(COPY_FILE) --parents $(SOURCES) $(DIST) .tmp/$(PROJECT_NAME)1.0.0/ && $(COPY_FILE) --parents ../$(PROJECT_NAME)/communicate.h .tmp/$(PROJECT_NAME)1.0.0/ && $(COPY_FILE) --parents ../$(PROJECT_NAME)/main.cpp ../$(PROJECT_NAME)/communicate.cpp .tmp/$(PROJECT_NAME)1.0.0/ && (cd `dirname .tmp/$(PROJECT_NAME)1.0.0` && $(TAR) $(PROJECT_NAME)1.0.0.tar $(PROJECT_NAME)1.0.0 && $(COMPRESS) $(PROJECT_NAME)1.0.0.tar) && $(MOVE) `dirname .tmp/$(PROJECT_NAME)1.0.0`/$(PROJECT_NAME)1.0.0.tar.gz . && $(DEL_FILE) -r .tmp/$(PROJECT_NAME)1.0.0 


clean:compiler_clean 
    -$(DEL_FILE) $(OBJECTS) 
    -$(DEL_FILE) *~ core *.core 


####### Sub-libraries 

distclean: clean 
    -$(DEL_FILE) $(TARGET) 

#-$(DEL_FILE) Makefile 


check: first 

mocclean: compiler_moc_header_clean compiler_moc_source_clean 

mocables: compiler_moc_header_make_all compiler_moc_source_make_all 

compiler_moc_header_make_all: moc_communicate.cpp 
compiler_moc_header_clean: 
    -$(DEL_FILE) moc_communicate.cpp 
moc_communicate.cpp: ../$(PROJECT_NAME)/communicate.h 
    $(QT_QMAKE)moc $(DEFINES) $(INCPATH) ../$(PROJECT_NAME)/communicate.h -o moc_communicate.cpp 

compiler_rcc_make_all: 
compiler_rcc_clean: 
compiler_image_collection_make_all: qmake_image_collection.cpp 
compiler_image_collection_clean: 
    -$(DEL_FILE) qmake_image_collection.cpp 
compiler_moc_source_make_all: 
compiler_moc_source_clean: 
compiler_uic_make_all: 
compiler_uic_clean: 
compiler_yacc_decl_make_all: 
compiler_yacc_decl_clean: 
compiler_yacc_impl_make_all: 
compiler_yacc_impl_clean: 
compiler_lex_make_all: 
compiler_lex_clean: 
compiler_clean: compiler_moc_header_clean 

####### Compile 

main.o: ../$(PROJECT_NAME)/main.cpp ../$(PROJECT_NAME)/communicate.h 
    $(CXX) -c $(CXXFLAGS) $(INCPATH) -o main.o ../$(PROJECT_NAME)/main.cpp 

communicate.o: ../$(PROJECT_NAME)/communicate.cpp ../$(PROJECT_NAME)/communicate.h 
    $(CXX) -c $(CXXFLAGS) $(INCPATH) -o communicate.o ../$(PROJECT_NAME)/communicate.cpp 

moc_communicate.o: moc_communicate.cpp 
    $(CXX) -c $(CXXFLAGS) $(INCPATH) -o moc_communicate.o moc_communicate.cpp 

####### Install 

install: FORCE 

uninstall: FORCE 

FORCE: 


  • 創建項目文件:Communicate.pro


QT  += core gui 

TARGET = Communicate 
TEMPLATE = app 


SOURCES += main.cpp\ 
     communicate.cpp 

HEADERS += communicate.h 


  • 設置自定義的Makefile ...項目 - >屬性:

Setup Makefile

  • 安裝運行動作......項目 - >屬性:

Set run action

  • 運行

Run

雖然是CB是與wxWidgets的,和C/C++一般工作的最佳環境,我個人認爲,在使用Qt工作的情況下,QtCreator提供了一個開發環境,多種天然和優化的工作你項目QT。