2012-12-23 18 views
29

Sono un principiante alla programmazione Qt e utilizzo di blocchi di codice per la mia programmazione. Ho creato 3 file communicate.h, commmunicate.cpp e Main.cpp come segue:Qt riferimento non definito a 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(); 
} 

e dei suoi errori mostrando come segue:

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 ===| 

ragazzi contribuiscono prego ... non mi posso capirlo ...

+2

fare in modo che il file di progetto (.pro) include il file communicate.h nella sezione intestazioni – Zeks

+0

Questo è un duplicato, non troppo localizzato –

+4

la risposta migliore che ho trovato, e che non è menzionato è quello di eseguire nuovamente qmake: http : //stackoverflow.com/a/3650758/258418 – ted

risposta

17

Si tratta di un bug sottile (e, probabilmente, in parte almeno di un bug del compilatore) che Ho visto prima. Poiché QWidget ha un distruttore virtuale, il compilatore ha bisogno di un vtable per la tua classe. Ma la tua classe non ha funzioni virtuali, quindi non ne ha creata una per la tua classe Communicate.

Aggiungi un virtual ~Communicate() {}; alla tua classe e tutto andrà bene.

Sì, mi ci è voluto del tempo per capire anche questo!

+7

Non sei corretto. Ho appena testato questa classe: class Test: public QObject {Q_OBJECT} e questo compila bene supponendo che il file di intestazione risieda in .pro Nel momento in cui commento, ottengo il riferimento undefinde a vtable – Zeks

+0

Ok, ho visto questo problema in un setup diverso, in cui QT non era affatto coinvolto, e il problema era causato dal non aver dichiarato un distruttore. Quindi può darsi che il MOC stia "sistemando" questo genere di cose al volo? –

+0

Il codice viene compilato correttamente se si aggiunge la comunicazione.h nella sezione HEADERS. – Kikohs

12

MOC (oggetto compilatore meta) ha bisogno di sapere della vostra communicate.h (così come di eventuali altre classi Q_OBJECT'ed) per fare il suo lavoro. A meno che non si inseriscono in un file .pro nella sezione HEADERS - si ottiene questo "undefined reference"

+0

Sto usando i blocchi di codice in Windows 7. Non riesco a trovare alcun file .pro con la directory del progetto ... puoi essere più specifico per favore? –

+0

@Zeks sì hai ragione, Qt ha bisogno di conoscere anche l'intestazione personalizzata – jondinham

18

Un'opzione veloce per risolvere il problema è quello di rimuovere il Q_OBJECT macro, questo vi permetterà di compilare e testare la vostra applicazione , ma, non è una scelta giusta, se si intende lavorare tutti i giorni con QT su CB è necessario configurare l'ambiente.

Un'opzione che personalmente mi piace di più e creare un makefile personalizzato e un file. "pro" per l'applicazione è facilmente trasportabile in altri ambienti come "QtCreator" "NetBeansIDE", ecc.

Spiegherò rapidamente quali sono i passi da seguire. Se hai installato QtCreator merita il supporto del file generato da QtCreator e con un po 'di esperienza puoi creare i tuoi file.

Questo esempio permettono solo di compilare ed eseguire il file sotto "Target di uscita" più avanti sarà necessario personalizzare l'ambiente di lavoro

  • creare il file: 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: 


  • Creare file di progetto: Communicate.pro


QT  += core gui 

TARGET = Communicate 
TEMPLATE = app 


SOURCES += main.cpp\ 
     communicate.cpp 

HEADERS += communicate.h 


  • Installazione personalizzata Makefile ... Progetto-> proprietà:

Setup Makefile

  • Setup azione ... Progetto-> Proprietà:

Set run action

  • Run

Run

Nonostante che CB è un ambiente ottimale per lavorare con wxWidgets, e C/C++, in generale, personalmente ritengo che, nel caso di lavorare con Qt, QtCreator fornisce un ambiente di sviluppo più nativo e ottimizzato per lavorare con il tuo progetti QT.