Qt undefined ссылка на vtable

Я новичок в программировании на Qt и использую кодовые блоки для программирования. Я создал 3 файла messages.h, commmunicate.cpp и main.cpp следующим образом:

общаться.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

communication.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();
}

и он показывает следующие ошибки:

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

ребята, помогите пожалуйста ... не могу понять ...


person Jijo    schedule 23.12.2012    source источник
comment
убедитесь, что ваш файл проекта (.pro) включает файл communication.h в разделе заголовков   -  person Zeks    schedule 23.12.2012
comment
Это дубликат, не слишком локализованный   -  person BЈовић    schedule 29.06.2013
comment
лучший ответ, который я нашел, и который здесь не упоминается, - это перезапустить qmake: stackoverflow.com/a/3650758/258418   -  person ted    schedule 28.04.2015
comment
Спасибо, Тед, твой повторный комментарий qmake - это то, что исправило для меня. Не уверен, когда и как возникла проблема, но что в конечном итоге исправило, так это ручное удаление файла Makefile, запускающее его регенерацию в Qt Creator.   -  person Stigz    schedule 10.10.2016
comment
@Jijo Jose и всем: я не уверен, что с моей системой что-то пойдет не так, но для меня удаление каталога сборки устранило проблему. (Даже Чистого всего не хватило). Я предполагаю, что это потому, что файл moc (сгенерированный) не может получить доступ к заголовку. Надеюсь, это кому-то поможет.   -  person michalis    schedule 25.03.2017
comment
Ответ Зекса работает у меня   -  person Sanbrother    schedule 07.03.2019
comment
Другая причина, по которой я столкнулся с той же проблемой, заключается в том, что по какой-то причине, если я не #include ‹QObject›, qmake не идентифицировал бы мой код как требующий MOCed (QObject был включен из другого включаемого файла). Добавление #include ‹QObject› исправило это.   -  person johnnyb    schedule 30.05.2019


Ответы (4)


Это тонкая ошибка (и, вероятно, частично, по крайней мере, ошибка компилятора), которую я видел раньше. Поскольку QWidget имеет виртуальный деструктор, компилятору нужна vtable для вашего класса. Но в вашем классе нет виртуальных функций, поэтому он не создавал их для вашего класса Communicate.

Добавьте virtual ~Communicate() {}; в свой класс, и все будет хорошо.

Да, мне тоже потребовалось время, чтобы понять это!

person Mats Petersson    schedule 23.12.2012
comment
Вы не правы. Я только что протестировал этот класс: class Test: public QObject {Q_OBJECT}, и он отлично компилируется, если файл заголовка находится в .pro. В тот момент, когда я его комментирую, я получаю ссылку undefinde на vtable - person Zeks; 23.12.2012
comment
Хорошо, я видел эту проблему в другой настройке, где QT вообще не участвовал, и проблема была вызвана отсутствием объявленного деструктора. Так может быть, MOC исправляет подобные вещи на лету? - person Mats Petersson; 23.12.2012
comment
Код компилируется нормально, если вы добавляете messages.h в раздел HEADERS. - person Kirell; 23.12.2012
comment
Я попытался добавить упомянутый u код в класс в разделе public: но проблема все еще не устранена ........... - person Jijo; 24.12.2012
comment
В классе есть виртуальные функции, они объявлены макросом Q_OBJECT. Почему этот ответ принят ?? - person Nicolás; 21.07.2017
comment
Спас мою жизнь, используя QObject и QGraphicsItem как общедоступные с сигналом / слотами - person Pixtar; 04.01.2018
comment
У меня все еще была эта проблема, пока я повторно не запустил qmake в меню сборки qtcreator. - person NuclearPeon; 03.08.2018

MOC (компилятор метаобъектов) должен знать о вашем файле communication.h (а также о любых других классах, связанных с Q_OBJECT), чтобы выполнять свою работу. Если вы не поместите их в файл .pro в разделе HEADERS - вы получите эту "неопределенную ссылку"

person Zeks    schedule 23.12.2012
comment
Я использую кодовые блоки в Windows 7. Я не могу найти ни одного файла .pro с каталогом проекта ... не могли бы вы уточнить, пожалуйста? - person Jijo; 24.12.2012
comment
@Zeks да, вы правы, Qt тоже нужно знать настраиваемый заголовок - person jondinham; 10.03.2014
comment
У меня были проблемы с компиляцией RedisQtAdapter из библиотеки hiredis, так как я получал ошибки компоновщика. Что на самом деле помогло - благодаря этому ответу - добавление, например, /usr/local/include/hiredis/adapters/qt.h в разделе ЗАГОЛОВКИ в файле .pro. - person Michal; 27.12.2018
comment
Это действительно довольно неожиданно для неопытного пользователя qmake. Особенно после CMake, который автоматически определяет все необходимые файлы заголовков. - person AleXoundOS; 06.03.2019

Быстрый вариант решения проблемы - удалить макрос Q_OBJECT, это позволит вам скомпилировать и протестировать приложение, но это неправильный выбор , если вы собираетесь работать каждый день с QT, на CB необходимо настроить вашу среду.

Один из вариантов, который мне лично нравится больше, и создание собственного make-файла и файла. "pro" для приложения его легко переносить в другие среды, такие как "QtCreator", "NetBeansIDE" и т. д.

Я быстро объясню, что нужно делать. Если вы установили QtCreator, заслуживает поддержки самогенерируемый QtCreator файл, и с небольшим опытом можете создавать свои собственные файлы.

Этот пример позволяет вам компилировать и запускать файлы только в «Целевом выпуске», позже вам придется настроить свою рабочую среду

  • Создать файл: 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:


  • Создать файл проекта: Communicate.pro


QT       += core gui

TARGET = Communicate
TEMPLATE = app


SOURCES += main.cpp\
        communicate.cpp

HEADERS  += communicate.h


  • Настроить пользовательский Makefile ... Проект-> свойства:

Настроить Makefile

  • Настройка Выполнить Действие ... Проект-> свойства:

Установить действие запуска

  • Бегать

Выполнить

Хотя этот CB является оптимальной средой для работы с wxWidgets и C / C ++ в целом, я лично считаю, что в случае работы с Qt QtCreator предоставляет среду разработки, более родную и оптимизированную для работы с вашими проектами QT.

person RTOSkit    schedule 23.12.2012

Вам нужно определить деструктор. Несмотря на то, что он является производным от QObject, компилятору недостаточно использовать конструктор / деструкторы по умолчанию.

Ошибка компоновщика Qt: неопределенная ссылка на vtable

person Blastcore    schedule 23.12.2012