2012-12-23 12 views
29

Jestem początkującym programistą Qt i używam bloków kodu dla mojego programowania. Stworzyłem 3 pliki communicate.h, commmunicate.cpp i main.cpp następująco:Qt niezdefiniowane odniesienie do 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(); 
} 

i jego błędy pokazujące jak następuje:

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

chłopaki proszę o pomoc ... nie mogę zrozumieć to ...

+2

upewnić się, że plik projektu (.pro) zawiera plik communicate.h w sekcji nagłówków – Zeks

+0

To jest duplikatem, niezbyt zlokalizowane –

+4

najlepszą odpowiedź znalazłem, a które nie są tutaj wymienione jest powtórzona qmake: http : //stackoverflow.com/a/3650758/258418 – ted

Odpowiedz

17

Jest to subtelny błąd (i zapewne częściowo przynajmniej błąd kompilatora), które Widziałem już wcześniej. Ponieważ QWidget ma wirtualny destruktor, kompilator potrzebuje vtable dla twojej klasy. Ale twoja klasa nie ma żadnych funkcji wirtualnych, więc nie zbudowała go dla twojej klasy komunikacyjnej.

Dodaj do swojej klasy virtual ~Communicate() {};, a wszystko będzie dobrze.

Tak, zajęło mi to trochę czasu!

+7

Nie masz racji. Właśnie przetestowałem tę klasę: test klasy: public QObject {Q_OBJECT} i to kompiluje się dobrze zakładając, że plik nagłówkowy znajduje się w .pro W chwili, gdy to skomentuję - otrzymuję odwołanie undefinde do vtable – Zeks

+0

Ok, widziałem ten problem w inna konfiguracja, w której QT w ogóle nie była zaangażowana, a przyczyną problemu był brak deklaracji destruktora. Być może MOC "naprawia" tego typu rzeczy w locie? –

+0

Kod kompiluje dobrze, jeśli dodasz komunikację.h w sekcji HEADERS. – Kikohs

12

MOC (meta obiekt kompilator) musi wiedzieć o swojej communicate.h (jak również wszelkich innych klasach Q_OBJECT'ed), aby wykonywać swoje zadania. Chyba, że ​​umieścić je w pliku .pro mocy sekcji nagłówków - dostaniesz to „niezdefiniowana odniesienia”

+0

Używam bloków kodu w systemie Windows 7. Nie mogę znaleźć żadnego pliku .pro z katalogiem projektu ... czy możesz bardziej konkretnie? –

+0

@Zeks tak, masz rację, Qt również musi znać niestandardowy nagłówek – jondinham

18

Szybkie opcji, aby rozwiązać ten problem jest do usunąć Q_OBJECT makro, pozwoli to na kompilacji i testowania aplikacji , ale nie jest to właściwy wybór, jeśli zamierzasz pracować codziennie z QT na CB, musisz skonfigurować swoje środowisko.

Jedna opcja, którą osobiście bardziej lubię i tworzę niestandardowy plik Makefile i plik. "pro" dla aplikacji jest łatwy do przenoszenia w innych środowiskach, jak "QtCreator" "NetBeansIDE", itp.

Szybko wyjaśni, jakie kroki należy wykonać. Jeśli zainstalowałeś QtCreator, zasługujesz na wsparcie generowane przez sam plik QtCreator, a przy odrobinie doświadczenia możesz tworzyć własne pliki.

Ten przykład tylko pozwalają kompilować i uruchamiać pliki w „target wydaniu” później trzeba będzie dostosować swoje środowisko pracy

  • Utwórz plik: 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: 


  • Tworzenie pliku projektu: Communicate.pro


QT  += core gui 

TARGET = Communicate 
TEMPLATE = app 


SOURCES += main.cpp\ 
     communicate.cpp 

HEADERS += communicate.h 


  • Instalacja niestandardowa Makefile ... projektu-> właściwości:

Setup Makefile

  • Run setup akcji ... Project-> właściwości:

Set run action

  • Run

Run

Mimo że CB to optymalne środowisko do pracy z wxWidgets i C/C++ w ogóle, ja osobiście uważam, że w przypadku pracy z Qt, Qt Creator zapewnia środowisko programistyczne więcej rodzimych i zoptymalizowane do pracy z projekty QT.

Powiązane problemy