This question already has an answer here:
-
Qt Linker Error: “undefined reference to vtable” [duplicate]
9 answers
I am a beginner to Qt programming and use codeblocks for my programming. I created 3 files communicate.h,commmunicate.cpp and main.cpp as follows:
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();
}
and its showing errors as follows:
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 ===|
guys please help...cant figure it out...
This is a subtle bug (and probably partly at least a compiler bug) that I've seen before. Since QWidget has a virtual destructor, the compiler needs a vtable for your class. But your class doesn't have any virtual functions, so it didn't build one for your Communicate class.
Add a virtual ~Communicate() {};
to your class, and all will be well.
Yes, it took me some time to figure this out too!
A quick option to solve the problem is to remove the Q_OBJECT macro, this will allow you to compile and test your application,
but, not a right choice, if you intend to work every day with QT on CB must configure your environment.
One option that I personally like more and create a custom makefile and a file. "pro" for the application it is easily transportable in other environments as "QtCreator" "NetBeansIDE", etc.
I'll quickly explain what are the steps to follow. If you have installed QtCreator deserves support of self-generated by QtCreator file, and with a little experience can build your own files.
This example only allow you to compile and run the files under "Target Release" later you will have to customize your work environment
####### 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 "$@" "$<"
.cc.o:
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<"
.cxx.o:
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<"
.C.o:
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<"
.c.o:
$(CC) -c $(CFLAGS) $(INCPATH) -o "$@" "$<"
####### 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:
- Create Project file: Communicate.pro
QT += core gui
TARGET = Communicate
TEMPLATE = app
SOURCES += main.cpp\
communicate.cpp
HEADERS += communicate.h
- Setup Custom Makefile ...Project->properties:
- Setup Run Action ...Project->properties:
Although that CB is an optimal environment for working with wxWidgets, and C/C++ in general, I personally think that in the case of working with Qt, QtCreator provides a development environment more native and optimized to work with your projects QT.
MOC(meta object compiler) needs to know of your communicate.h (as well as of any other Q_OBJECT'ed classes) to do its job. Unless you place them into .pro file under HEADERS section - you will get this "undefined reference"
You need to define the destructor. Even though it derives from a QObject it's not enough for the compiler to use default constructor/destructors.
Qt Linker Error: "undefined reference to vtable"