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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 17:53:23  来源:igfitidea点击:

Qt undefined reference to vtable

c++user-interfaceqt4codeblocks

提问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 Makefile

设置 Makefile

  • Setup Run Action ...Project->properties:
  • 设置运行操作...项目->属性:

Set run action

设置运行动作

  • Run

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,它也不足以让编译器使用默认的构造函数/析构函数。

Qt Linker Error: "undefined reference to vtable"

Qt 链接器错误:“对 vtable 的未定义引用”