C++ Qt 对 vtable 的未定义引用
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/14010922/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Qt undefined reference to vtable
提问by Jijo Jose
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:
我是 Qt 编程的初学者,并在我的编程中使用代码块。我创建了3个文件communication.h、commmunicate.cpp和main.cpp,如下所示:
communicate.h
沟通.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
沟通.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.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.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...
伙计们请帮助...无法弄清楚...
采纳答案by Mats Petersson
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.
这是我以前见过的一个微妙的错误(可能至少部分是编译器错误)。由于 QWidget 有一个虚拟析构函数,编译器需要一个 vtable 用于您的类。但是你的类没有任何虚函数,所以它没有为你的 Communicate 类构建一个。
Add a virtual ~Communicate() {};
to your class, and all will be well.
添加一个virtual ~Communicate() {};
到你的班级,一切都会好起来的。
Yes, it took me some time to figure this out too!
是的,我也花了一些时间才弄明白这一点!
回答by Zeks
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"
MOC(元对象编译器)需要知道你的communication.h(以及任何其他Q_OBJECT'ed 类)来完成它的工作。除非您将它们放入 HEADERS 部分下的 .pro 文件中 - 您将获得此“未定义的引用”
回答by RTOSkit
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.
解决问题的一个快速选项是删除 Q_OBJECT 宏,这将允许您编译和测试您的应用程序, 但是,这不是一个正确的选择,如果您打算每天在 CB 上使用 QT 必须配置您的环境。
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.
我个人更喜欢的一个选项是创建一个自定义的 makefile 和一个文件。应用程序的“pro”,它可以在其他环境中轻松传输,如“QtCreator”“NetBeansIDE”等。
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.
我将快速解释要遵循的步骤。如果你已经安装了 QtCreator 值得支持由 QtCreator 自行生成文件,并且有一点经验可以构建你自己的文件。
This example only allow you to compile and run the files under "Target Release" later you will have to customize your work environment
此示例仅允许您编译和运行“目标版本”下的文件,稍后您将不得不自定义您的工作环境
- Create file: Makefile
- 创建文件: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 "$@" "$<"
.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
- 创建项目文件:Communicate.pro
QT += core gui
TARGET = Communicate
TEMPLATE = app
SOURCES += main.cpp\
communicate.cpp
HEADERS += communicate.h
- Setup Custom Makefile ...Project->properties:
- 设置自定义 Makefile ...项目-> 属性:
- Setup Run Action ...Project->properties:
- 设置运行操作...项目->属性:
- Run
- 跑
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.
虽然 CB 是使用 wxWidgets 和 C/C++ 的最佳环境,但我个人认为,在使用 Qt 的情况下,QtCreator 提供了一个更原生和优化的开发环境,以与您的项目 QT 一起使用。
回答by Blastcore
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.
您需要定义析构函数。即使它派生自 QObject,它也不足以让编译器使用默认的构造函数/析构函数。