Меню

Undefined reference to vtable for qt ошибка

I’m using Code::Blocks 8.02 and the mingw 5.1.6 compiler. I’m getting this error when I compile my Qt project:

C:Documents and SettingsThe
FuzzDesktopGUIApp_interface.cpp|33|undefined
reference to `vtable for AddressBook’

File AddressBook.h:

 #ifndef ADDRESSBOOK_H
 #define ADDRESSBOOK_H

 #include <QWidget>

 class QLabel;
 class QLineEdit;
 class QTextEdit;

 class AddressBook : public QWidget
 {
     Q_OBJECT

 public:
     AddressBook(QWidget *parent = 0);

 private:
     QLineEdit *nameLine;
     QTextEdit *addressText;
 };

 #endif

File AddressBook.cpp:

#include <QtGui>
#include "addressbook.h"

AddressBook::AddressBook(QWidget *parent)
     : QWidget(parent)
{
    QLabel *nameLabel = new QLabel(tr("Name:"));
    nameLine = new QLineEdit;

    QLabel *addressLabel = new QLabel(tr("Address:"));
    addressText = new QTextEdit;

    QGridLayout *mainLayout = new QGridLayout;
    mainLayout->addWidget(nameLabel, 0, 0);
    mainLayout->addWidget(nameLine, 0, 1);
    mainLayout->addWidget(addressLabel, 1, 0, Qt::AlignTop);
    mainLayout->addWidget(addressText, 1, 1);

    setLayout(mainLayout);
    setWindowTitle(tr("Simple Address Book"));
}

ymoreau's user avatar

ymoreau

3,2721 gold badge19 silver badges56 bronze badges

asked Oct 11, 2009 at 23:25

TheFuzz's user avatar

When using Qt Creator:

  1. Build → Run qmake
  2. Build → Rebuild All

Honest Abe's user avatar

Honest Abe

8,2204 gold badges47 silver badges63 bronze badges

answered Jul 14, 2010 at 17:21

Anurag Verma's user avatar

3

Warning: Do not do this if you already have a .pro file — you’ll lose it!

In order to automatically ensure that all moc cpp files are generated, you can get qmake to automatically generate a .pro file for you instead of writing one yourself.

Run

qmake -project

in the project directory, and qmake will scan your directory for all C++ headers and source files to generate moc cpp files for.

Kuba hasn't forgotten Monica's user avatar

answered Oct 12, 2009 at 4:51

blwy10's user avatar

blwy10blwy10

4,8622 gold badges24 silver badges23 bronze badges

5

The problem is almost certainly that you are not compiling or not linking in the generated moc_AddressBook.cpp file. (It should have been generated for you — you are running Qt’s moc on your code before compiling, right?)

To answer a little more thoroughly, the Q_OBJECT macro signals Qt’s moc tool to create an extra implementation file that contains the code necessary to support QObject‘s meta-information system. If you had any signals or slots, it would do a few things for those as well.

An alternative solution might be to remove the Q_OBJECT macro. You probably don’t want to do this, but it would help the immediate problem, and it isn’t strictly necessary with the code that you’ve presented.

Also, I would note that your line:

#include "addressbook.h"

Should probably be:

#include "AddressBook.h"

based on how you presented the filenames in the question.

answered Oct 12, 2009 at 0:53

Caleb Huitt - cjhuitt's user avatar

2

Assuming you are using qmake to generate your Makefile, be sure that AddressBook.h is specified in your .pro file’s HEADERS’s variable, e.g.

HEADERS = AddressBook.h

answered Oct 12, 2009 at 2:18

Jeremy Friesner's user avatar

Jeremy FriesnerJeremy Friesner

67.4k15 gold badges126 silver badges225 bronze badges

3

For CMake projects, set CMAKE_AUTOMOC to ON, this fixed my problem.

#Find includes in corresponding build directories
set(CMAKE_INCLUDE_CURRENT_DIR ON)

# Instruct CMake to run moc automatically when needed.
set(CMAKE_AUTOMOC ON)

answered Nov 15, 2017 at 13:28

Dumisani Kunene's user avatar

I got this while using pure virtual functions. For example,

virtual void process();

gave this error, while

virtual void process() = 0;

made it go away.

For anyone who’s Googling this problem, check that all virtual functions are defined. (via » = 0″ or a full definition in the source file)
I’m using Netbeans with the MinGW compiler.

Community's user avatar

answered Apr 2, 2011 at 5:14

1

I had the same problem but as soon as I defined my constructor in the header file instead of the .cpp the error disappeared. Also the corresponding moc file was missing in the file system and in the Makefile section»compiler_moc_header_make_all» . I ran a qmake then finally everything built with succes. I went to check the Makefile and it was there now.

answered Dec 2, 2009 at 19:54

yan bellavance's user avatar

yan bellavanceyan bellavance

4,65020 gold badges60 silver badges92 bronze badges

0

deleted the build folder, restarted Qt Creator and it worked

answered Mar 29, 2011 at 12:51

yolo's user avatar

yoloyolo

2,7456 gold badges36 silver badges65 bronze badges

1

I come to the same problem, rebuild the project never update the Makefile, I remove the Makefile and rebuild , the the problem is gone.
ps: run ‘make’ from command line may give you detail information than the IDE, and helpful to get the real problem.

answered Feb 26, 2010 at 2:55

user281754's user avatar

One cause is when you declare a virtual functions in a class and you don’t define their body.

BenMorel's user avatar

BenMorel

33.3k49 gold badges174 silver badges309 bronze badges

answered Nov 7, 2011 at 13:03

agus's user avatar

In my case Rebuild All was not enough, I had to delete build directory and make Rebuild All — then it worked!

answered Apr 19, 2015 at 20:58

Aleksei Petrenko's user avatar

Aleksei PetrenkoAleksei Petrenko

6,30010 gold badges52 silver badges86 bronze badges

1

Simply Run qmake for your project. This can easily be done by right-clicking on the name of your project and clicking on Run qmake.

answered Jan 8, 2019 at 5:18

Sunit Gautam's user avatar

Sunit GautamSunit Gautam

4,9652 gold badges18 silver badges30 bronze badges

Just clear the project and then rebuild it!

answered Mar 30, 2020 at 19:51

Hamed's user avatar

HamedHamed

365 bronze badges

Go to .pro file and make sure .h file has ‘include’ before it.
HEADERS += include/file.h
include/file2.h

answered Aug 10, 2010 at 18:22

Phil's user avatar

PhilPhil

4053 silver badges14 bronze badges

I had the same problem trying to use a protected virtual function. Two things worked.

  1. Changing void process(); to void process() = 0;
  2. Making process() public instead of private

answered Oct 6, 2014 at 21:34

khafen's user avatar

khafenkhafen

1414 bronze badges

You will get the same error message if you accidentally add a destructor prototype. Add an empty destructor definition or remove the prototype.

answered Nov 8, 2017 at 9:29

Emil Fors's user avatar

Header files for moc compilation should contained in the HEADERS += … variable:

I have moved the header files in the Myproject.pro to the SOURCES += … section, because I want to have mySource.h and mySource.cpp in the same tree element. But that is faulty for QT Creator. In result the error «Undefined reference to vtable» has occured.
It seems to be:
QT detects header for moc compilation only in the HEADERS +=… section (or variable).
See also the correct explaination in the other stackoverflow answer Second anwer «I’ve seen a lot of ways to solve the problem, but no explanation for why it happens, so here goes.». In my mind this is an exactly explaination of the problem, which has help me to found and solve my problem.

answered Aug 15, 2019 at 8:58

Hartmut Schorrig's user avatar

CMake

when using CMake, interestingly enough if my .cpp and .h files are not in the same folder the moc, bu default, fails to generate the meta file 🙂

answered Mar 3, 2021 at 13:10

Goran Shekerov's user avatar

I am using Qt creator to compile and run my programs, I don’t use Qt command prompt often. One thing I did to get rid of the annoying error «vtable something something» is by adding the following lines to .pro file.

TEMPLATE = app

QT += core

christangrant's user avatar

answered Sep 19, 2014 at 3:54

Mmakgabo Makgoba's user avatar

1

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:

objDebugmain.o(.text$_ZN11CommunicateD1Ev[Communicate::~Communicate()]+0xb)||In function `ZN7QStringC1EPKc':|
C:Qt4.4.3includeQtCore....srccorelibarchqatomic_windows.h||undefined reference to `vtable for Communicate'|
objDebugmain.o(.text$_ZN11CommunicateD1Ev[Communicate::~Communicate()]+0x17):C:Qt4.4.3includeQtCore....srccorelibarchqatomic_windows.h||undefined reference to `vtable for Communicate'|
objDebugcommunicate.o(.text+0x172)||In function `ZN11CommunicateC2EP7QWidget':|
E:Projectcam2communicate.cpp|5|undefined reference to `vtable for Communicate'|
objDebugcommunicate.o(.text+0x17e):E:Projectcam2communicate.cpp|5|undefined reference to `vtable for Communicate'|
objDebugcommunicate.o(.text+0x63a)||In function `ZN11CommunicateC1EP7QWidget':|
E:Projectcam2communicate.cpp|5|undefined reference to `vtable for Communicate'|
objDebugcommunicate.o(.text+0x646):E:Projectcam2communicate.cpp|5|more undefined references to `vtable for Communicate' follow|
||=== Build finished: 6 errors, 0 warnings ===|

guys please help…cant figure it out…

Автор Тема: Если вылезает ошибка «undefined reference to vtable for …» [СОВЕТ]  (Прочитано 55263 раз)
frostyland

Гость


Если при компиляции появляется ошибка такого рода
undefined reference to vtable for (имя_класса)
то,
1. Вероятно, вы объявили, но забыли реализовать один или несколько виртуальных методов класса, не наследованного от QObject.
2. от пользователя ufna):

хз, на моей практике такая ошибка возникает когда Q_OBJECT забыл добавить, затем вставляешь, но qmake заново не делаешь ))

« Последнее редактирование: Сентябрь 30, 2010, 13:35 от frostyland »
Записан
zenden

Гость


а может просто запустить qmake?? (очень часто указанная ошибка возникает из за отсутствия файла moc)


Записан
frostyland

Гость


а может просто запустить qmake?? (очень часто указанная ошибка возникает из за отсутствия файла moc)

в моем случае не помогло. да и не могло помочь: объявил — реализуй!
просто само сообщение не говорит конкретно в чем ошибка. Поэтому и отписался — чтобы народ не тратил по полчаса-часу, как я )


Записан
navrocky

Гипер активный житель
*****
Offline Offline

Сообщений: 817

Погроммист

Просмотр профиля


То же самое с любым виртуальным методом, который не реализован. Плюс если объявляешь Q_OBJECT но не прогоняешь по нему moc такая же ошибка, частенько встречается когда используется cmake в качестве системы сборки. Или в случае с qmake когда Q_OBJECT объявлен в cpp.


Записан

Гугль в помощь

frostyland

Гость


Блин, ребята.
Ну читайте внимательно, что ли…
Если не реализовал вирт.метод SomeMethod, то компилятор ругается предметно:

undefined reference to ‘SomeMethod’

, и становится ежу понятно, где грабли.

А здесь ругань на vtable для класса, а никак не на

undefined reference to ‘~SomeDestructor’

Мой пост для того, чтобы помочь разобраться в этом, только и делов.


Записан
pastor

Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 2901

Просмотр профиля
WWW


Блин, ребята.
Ну читайте внимательно, что ли…
Если не реализовал вирт.метод SomeMethod, то компилятор ругается предметно:

Неверно. Как раз будт ошибка линковки:

Undefined reference to ‘vtable for …’


Записан

pastor

Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 2901

Просмотр профиля
WWW


Для интереса собери код:

C++ (Qt)

class IClass
{
public:
   virtual void foo() = 0;
};

 class MyClass : public IClass
{
public:
   void foo();
};

 MyClass x;

и получишь

Undefined reference to ‘vtable for MyClass’

Деструктор здесь не причем.

« Последнее редактирование: Сентябрь 30, 2010, 12:56 от pastor »
Записан

frostyland

Гость


Уважаемый pastor.
Только что провел еще один тест.
Если класс наследован от QObject, то компилятор в обоих случаях ругается правильно:

В семпле поставляемом с QtCreator 2.0 — browser.pro
Закомментировал mousePressEvent(QMouseEvent*)
Ругается:

undefined reference to `WebView::mousePressEvent(QMouseEvent*)’

Объявил, но не стал реализовывать ~WebView.
Ругнулся правильно

undefined reference to `WebView::~WebView

В моем случае наследование не от QObject:

при нереализованном виртуальном методе

undefined reference [b]to `Vcon::PluginItem::type() const’
[/b]collect2: ld returned 1 exit status

При нереализованном виртуальном деструкторе:

./debugpluginmanager.o: In function `PluginItem’:
V:workQtvconsrcvcon-build-desktop/../vcon/pluginmanager.cpp:358: undefined reference [b]to `vtable for Vcon::PluginItem’ [/b]
V:workQtvconsrcvcon-build-desktop/../vcon/pluginmanager.cpp:358: undefined reference [b]to `vtable for Vcon::PluginItem’ [/b]
collect2: ld returned 1 exit status

Для чистоты эксперимента в вышеназванном проекте browser сделал виртуальным деструктор ~BookmarkNode();
До виртуализации при отсутствии реализации компилятор правильно ругался на

C:Qt2010.04qtdemosbrowser-build-desktop/../browser/bookmarks.cpp:299: undefined reference [b]to `BookmarkNode::~BookmarkNode()'[/b]

а с виртуализацией

C:Qt2010.04qtdemosbrowser-build-desktop/../browser/xbel.cpp:49: undefined reference [b]to `vtable for BookmarkNode’ [/b]


Записан
frostyland

Гость


Ну да. При сборке IClass все как Вы сказали.
Надо резюмировать как-то )
Например, ошибка с vtable может возникнуть в случае отсутствия реализации части виртуальных методов. Как-то так?


Записан
ufna

Гость


хз, на моей практике такая ошибка возникает когда Q_OBJECT забыл добавить, затем вставляешь, но qmake заново не делаешь ))


Записан
pastor

Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 2901

Просмотр профиля
WWW


Теперь берем тотже пример и делаем вызов foo():

C++ (Qt)

class IClass
{
public:
   virtual void foo() = 0;
};

 class MyClass : public IClass
{
public:
   void foo();
};

 MyClass x;
x.foo();

Смотрм, что получилось Улыбающийся

Думаю сейчас все станет ясно


Записан

kdm

Гость


Очень дельный совет, у меня такое часто когда-то случалось. В такие моменты я вообще был в растерянности и пересоздавал набор файлов класса *.cpp, *.h.

« Последнее редактирование: Октябрь 02, 2010, 18:41 от kdm »
Записан
frostyland

Гость


Теперь берем тотже пример и делаем вызов foo():

Думаю сейчас все станет ясно

Да, я примерил пример, и поправил первое сообщение. Вполне возможно, кому-то будет полезно.


Записан
blood_shadow

Гость


То же самое с любым виртуальным методом, который не реализован. Плюс если объявляешь Q_OBJECT но не прогоняешь по нему moc такая же ошибка, частенько встречается когда используется cmake в качестве системы сборки. Или в случае с qmake когда Q_OBJECT объявлен в cpp.

у меня с qmake такое получилось(программа состоит с одного файла .срр) закоментил Q_OBJECT в файле cpp и все стало норм. Кто знает из-за чего это? Баг линкера?
и еще как тогда реализовать сигналы и слоты если приходиться выбрасывать макрос Q_OBJECT() ?
вот код к примеру:

#include <iostream>
#include <QMainWindow>
#include <QtGui/QApplication>
#include <QObject>

using std::cout;
using std::endl;

class Test : public QMainWindow
{
    //Q_OBJECT;

public:
    Test(QWidget *parent = 0) : QMainWindow(parent) {}
    void Click() { setWindowFilePath(«file.txt»); }
    ~Test() {}

};

int main(int argc, char *argv[])
{

    QApplication app(argc, argv);

    Test test;
    test.show();

    return app.exec();

}


Записан
alexman

Гость


; попробуй убрать!


Записан

Following example from this link: http://developer.kde.org/documentation/books/kde-2.0-development/ch03lev1sec3.html

#include <QObject>
#include <QPushButton>
#include <iostream>
using namespace std;

class MyWindow : public QWidget
{
    Q_OBJECT  // Enable slots and signals
    public:
        MyWindow();
    private slots:
        void slotButton1();
        void slotButton2();
        void slotButtons();
    private:
        QPushButton *button1;
        QPushButton *button2;
};

MyWindow :: MyWindow() : QWidget()
{
    // Create button1 and connect button1->clicked() to this->slotButton1()
    button1 = new QPushButton("Button1", this);
    button1->setGeometry(10,10,100,40);
    button1->show();
    connect(button1, SIGNAL(clicked()), this, SLOT(slotButton1()));

    // Create button2 and connect button2->clicked() to this->slotButton2()
    button2 = new QPushButton("Button2", this);
    button2->setGeometry(110,10,100,40);
    button2->show();
    connect(button2, SIGNAL(clicked()), this, SLOT(slotButton2()));

    // When any button is clicked, call this->slotButtons()
    connect(button1, SIGNAL(clicked()), this, SLOT(slotButtons()));
    connect(button2, SIGNAL(clicked()), this, SLOT(slotButtons()));
}

// This slot is called when button1 is clicked.
void MyWindow::slotButton1()
{
    cout << "Button1 was clicked" << endl;
}

// This slot is called when button2 is clicked
void MyWindow::slotButton2()
{
    cout << "Button2 was clicked" << endl;
}

// This slot is called when any of the buttons were clicked
void MyWindow::slotButtons()
{
    cout << "A button was clicked" << endl;
}

int main ()
{
    MyWindow a;
}

results in:

    [13:14:34 Mon May 02] ~/junkPrograms/src/nonsense  $make
g++ -c -m64 -pipe -O2 -Wall -W -D_REENTRANT -DQT_NO_DEBUG -DQT_GUI_LIB -DQT_CORE_LIB -DQT_SHARED -I/opt/qtsdk-2010.05/qt/mkspecs/linux-g++-64 -I. -I/opt/qtsdk-2010.05/qt/include/QtCore -I/opt/qtsdk-2010.05/qt/include/QtGui -I/opt/qtsdk-2010.05/qt/include -I. -I. -o signalsSlots.o signalsSlots.cpp
g++ -m64 -Wl,-O1 -Wl,-rpath,/opt/qtsdk-2010.05/qt/lib -o nonsense signalsSlots.o    -L/opt/qtsdk-2010.05/qt/lib -lQtGui -L/opt/qtsdk-2010.05/qt/lib -L/usr/X11R6/lib64 -lQtCore -lpthread
signalsSlots.o: In function `MyWindow::MyWindow()':
signalsSlots.cpp:(.text+0x1a2): undefined reference to `vtable for MyWindow'
signalsSlots.cpp:(.text+0x1aa): undefined reference to `vtable for MyWindow'
signalsSlots.o: In function `MyWindow::MyWindow()':
signalsSlots.cpp:(.text+0x3e2): undefined reference to `vtable for MyWindow'
signalsSlots.cpp:(.text+0x3ea): undefined reference to `vtable for MyWindow'
signalsSlots.o: In function `main':
signalsSlots.cpp:(.text+0x614): undefined reference to `vtable for MyWindow'
signalsSlots.o:signalsSlots.cpp:(.text+0x61d): more undefined references to `vtable for MyWindow' follow
collect2: ld returned 1 exit status
make: *** [nonsense] Error 1

vtable is for virtual functions, AFAIK, what’s the reason of error here?

Following example from this link: http://developer.kde.org/documentation/books/kde-2.0-development/ch03lev1sec3.html

#include <QObject>
#include <QPushButton>
#include <iostream>
using namespace std;

class MyWindow : public QWidget
{
    Q_OBJECT  // Enable slots and signals
    public:
        MyWindow();
    private slots:
        void slotButton1();
        void slotButton2();
        void slotButtons();
    private:
        QPushButton *button1;
        QPushButton *button2;
};

MyWindow :: MyWindow() : QWidget()
{
    // Create button1 and connect button1->clicked() to this->slotButton1()
    button1 = new QPushButton("Button1", this);
    button1->setGeometry(10,10,100,40);
    button1->show();
    connect(button1, SIGNAL(clicked()), this, SLOT(slotButton1()));

    // Create button2 and connect button2->clicked() to this->slotButton2()
    button2 = new QPushButton("Button2", this);
    button2->setGeometry(110,10,100,40);
    button2->show();
    connect(button2, SIGNAL(clicked()), this, SLOT(slotButton2()));

    // When any button is clicked, call this->slotButtons()
    connect(button1, SIGNAL(clicked()), this, SLOT(slotButtons()));
    connect(button2, SIGNAL(clicked()), this, SLOT(slotButtons()));
}

// This slot is called when button1 is clicked.
void MyWindow::slotButton1()
{
    cout << "Button1 was clicked" << endl;
}

// This slot is called when button2 is clicked
void MyWindow::slotButton2()
{
    cout << "Button2 was clicked" << endl;
}

// This slot is called when any of the buttons were clicked
void MyWindow::slotButtons()
{
    cout << "A button was clicked" << endl;
}

int main ()
{
    MyWindow a;
}

results in:

    [13:14:34 Mon May 02] ~/junkPrograms/src/nonsense  $make
g++ -c -m64 -pipe -O2 -Wall -W -D_REENTRANT -DQT_NO_DEBUG -DQT_GUI_LIB -DQT_CORE_LIB -DQT_SHARED -I/opt/qtsdk-2010.05/qt/mkspecs/linux-g++-64 -I. -I/opt/qtsdk-2010.05/qt/include/QtCore -I/opt/qtsdk-2010.05/qt/include/QtGui -I/opt/qtsdk-2010.05/qt/include -I. -I. -o signalsSlots.o signalsSlots.cpp
g++ -m64 -Wl,-O1 -Wl,-rpath,/opt/qtsdk-2010.05/qt/lib -o nonsense signalsSlots.o    -L/opt/qtsdk-2010.05/qt/lib -lQtGui -L/opt/qtsdk-2010.05/qt/lib -L/usr/X11R6/lib64 -lQtCore -lpthread
signalsSlots.o: In function `MyWindow::MyWindow()':
signalsSlots.cpp:(.text+0x1a2): undefined reference to `vtable for MyWindow'
signalsSlots.cpp:(.text+0x1aa): undefined reference to `vtable for MyWindow'
signalsSlots.o: In function `MyWindow::MyWindow()':
signalsSlots.cpp:(.text+0x3e2): undefined reference to `vtable for MyWindow'
signalsSlots.cpp:(.text+0x3ea): undefined reference to `vtable for MyWindow'
signalsSlots.o: In function `main':
signalsSlots.cpp:(.text+0x614): undefined reference to `vtable for MyWindow'
signalsSlots.o:signalsSlots.cpp:(.text+0x61d): more undefined references to `vtable for MyWindow' follow
collect2: ld returned 1 exit status
make: *** [nonsense] Error 1

vtable is for virtual functions, AFAIK, what’s the reason of error here?

Программируя на Qt и время от времени проверяя форумы, приходится наблюдать, что программисты часто борятся с сообщениями вида «undefined reference to vtable».
Попробую описать ситуации, когда может возникнуть данная ошибка, и дать несколько советов, как избежать её.
Чаще всего данное сообщение всплывает, если вы используете MOC.
MOC (Meta-Object Compiler, переводится как Метаобъектная система/компилятор) – механизм, который расширяет синтаксис C++.
MOC:

  • необходим для механизма сигналов-слотов;
  • позволяет программисту получать метаинформацию о подклассах QObject (QObject::metaObject());
  • используется для интернационализации приложений (QObject::tr());
  • содержит в себе полезные расширения синтаксиса C++.

MOC компилятор находит и обрабатывает все заголовочные проекта.
При появлении ошибки «undefined reference to vtable», первым делом очистите проект и пересоберите его, не забыв запустить qmake:
make clean
# удалите вручную все moc-файлы, если они остались после выполнения make clean
rm Makefile
qmake
make

Если ошибка не исчезла, то проверьте файл проекта (*.pro). Проверьте, чтобы все необходимые заголовочные файлы (включающие сигналы и слоты особенно) были включены в проект. Список заголовочных файлов должен содержаться в переменной HEADERS:
HEADERS += firstHeaderFile.h
otherHeaderFile.h
secondHeaderFile.h

Если вы используете в проекте папку, содержащую заголовочные файлы, убедитесь, что добавили эту папку в переменную INCLUDEPATH:
INCLUDEPATH += ./include
Если обнаружили забытый h-, hpp-файл – пересоберите проект заново.
Проблема осталась? Тогда ещё варианты:

  1. Загляните в c-, cpp-файлы и убедитесь, что классы там не определяются. MOC разбирает только заголовочные файлы;
  2. Каждый класс, который имеет сигналы или слоты должен наследоваться от QObject, напрямую или нет.
    В начале определения таких классов обязательно должнен стоять макрос Q_OBJECT, к примеру:class MyWidget : public QWidget
    {
    Q_OBJECT
    /* класс наследуется от QWidget, а значит и от QObject,
    * следовательно должен содержать макрос Q_OBJECT.
    * Если класс наследуется от QObject, но не содержит сигналов или слотов,
    * то не обязательно включать макрос в описание класса.
    */
    ...
    }
  3. Ещё одна вещь, которую можно проверить.
    Удалите Makefile и посмотрите, что выдаст qmake в Makefile:

    rm Makefile
    qmake

    Откройте Makefile редактором и найдите следующие строки:

    compiler_moc_header_make_all:
    и
    compiler_moc_header_clean:

    Например, в моем Makefile есть: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:
    release/moc_mainwindow.cpp release/moc_SystemConfiguration.cpp release/moc_InstrumentConfiguration.cpp release/moc_ModuleConfiguration.cpp release/moc_ChannelConfiguration.cpp
    compiler_moc_header_clean:
    -$(DEL_FILE) releasemoc_mainwindow.cpp releasemoc_SystemConfiguration.cpp releasemoc_InstrumentConfiguration.cpp releasemoc_ModuleConfiguration.cpp releasemoc_ChannelConfiguration.cpp

    Каждый заголовочный файл, содержащийся в проекте и
    нуждающийся в обработке MOC-компилятора, должен находиться в этих строках.
    Имя файла будет начинаться с прифекса «moc_».
    Проверьте, что в список включены все h-файлы (точнее, только те, которые требуют обработку MOC-компилятором).
    Если Вы не обнаружили какой-либо moc-файл, не спешите править руками Makefile,
    просто подправьте pro-файл нужным образом.
    Если файл проекта правилен, то qmake генерирует правильный Makefile.

link

Есть пример кода из книги Шлее о Qt 5.3. Он разбросан на хедер Progress.h, где лежит определение класса Progress, Progress.cpp, где лежат определения методов этого класса, и основной файл main.cpp. Я закинул все в один файл main.cpp.

// Как бы файл Progress.h
#include <QApplication>
#include <QtWidgets>
#include <QProgressBar>
#include <QPushButton>

// ======================================================================
class Progress : public QWidget {
    Q_OBJECT
private:
    QProgressBar* m_pprb;
    int           m_nStep;

public:
    Progress(QWidget* pobj = 0);

public slots:
    void slotStep ();
    void slotReset();
};

// ----------------------------------------------------------------------
Progress::Progress(QWidget* pwgt/*= 0*/)
    : QWidget(pwgt)
    , m_nStep(0)
{
    m_pprb = new QProgressBar;
    m_pprb->setRange(0, 5);
    m_pprb->setMinimumWidth(200);
    m_pprb->setAlignment(Qt::AlignCenter);

    QPushButton* pcmdStep  = new QPushButton("&Step");
    QPushButton* pcmdReset = new QPushButton("&Reset");

    QObject::connect(pcmdStep, SIGNAL(clicked()), SLOT(slotStep()));
    QObject::connect(pcmdReset, SIGNAL(clicked()), SLOT(slotReset()));

    //Layout setup
    QHBoxLayout* phbxLayout = new QHBoxLayout;
    phbxLayout->addWidget(m_pprb);
    phbxLayout->addWidget(pcmdStep);
    phbxLayout->addWidget(pcmdReset);
    setLayout(phbxLayout);
}
// Как бы файл Progress.cpp
// ----------------------------------------------------------------------
void Progress::slotStep()
{
    m_pprb->setValue(++m_nStep);
}

// ----------------------------------------------------------------------
void Progress::slotReset()
{
    m_nStep = 0;
    m_pprb->reset();
}
// Как бы файл main()
// ----------------------------------------------------------------------
int main (int argc, char** argv)
{
    QApplication app(argc, argv);
    Progress     progress;

    progress.show();

    return app.exec();
}

В этом случае файл не компилируется, вылетают ошибки:

main.o: In function `Progress::Progress(QWidget*)':
/mnt/data-disk/MEGA/Programming/C++/build-untitled1-Desktop-Debug/../untitled1/main.cpp:24: undefined reference to `vtable for Progress'
/mnt/data-disk/MEGA/Programming/C++/build-untitled1-Desktop-Debug/../untitled1/main.cpp:24: undefined reference to `vtable for Progress'
main.o: In function `Progress::~Progress()':
/mnt/data-disk/MEGA/Programming/C++/build-untitled1-Desktop-Debug/../untitled1/main.cpp:7: undefined reference to `vtable for Progress'
/mnt/data-disk/MEGA/Programming/C++/build-untitled1-Desktop-Debug/../untitled1/main.cpp:7: undefined reference to `vtable for Progress'

Подскажите пожалуйста, почему так?

This topic has been deleted. Only users with topic management privileges can see it.

  • Hi everybody, I got a big problem … I want to connect a PushButton with a slot to save some parameters but I have an error when I make the project…

    So my H file is :
    @#ifndef CONFIGRS232_H
    #define CONFIGRS232_H

    #include <QtGui>
    #include <QWidget>

    class ConfigRS232: public QWidget
    {
    Q_OBJECT

    QPushButton *saveConfigButton;
    

    public:
    ConfigRS232(QWidget *parent = 0);

    private:
    int _portCom;
    int _baudRate;
    int _dataLength;
    int _parity;
    int _stopBit;

    QComboBox *portCom;
    QComboBox *baudRate;
    QComboBox *dataLength;
    QComboBox *parity;
    QComboBox *stopBit;
    

    public slots:
    void SaveConfigParameters();
    };

    #endif // CONFIGRS232_H@

    And my .cpp file is
    @#include «configrs232.h»

    #include <iostream>
    using namespace std;

    ConfigRS232::ConfigRS232(QWidget *parent)
    : QWidget(parent)
    {
    QGroupBox *rs232ConfigGroup = new QGroupBox(tr(«RS232 Configuration»));

    QLabel *pComLabel = new QLabel(tr("Com Port #"));
    portCom = new QComboBox;
    QLabel *pBaudLabel = new QLabel(tr("Bite Rate (bps):"));
    baudRate = new QComboBox;
    QLabel *pDataLabel = new QLabel(tr("Data Length:"));
    dataLength = new QComboBox;
    QLabel *pParLabel = new QLabel(tr("Parity:"));
    parity = new QComboBox;
    QLabel *pStopLabel = new QLabel(tr("Stop Bit:"));
    stopBit = new QComboBox;
    
    portCom->addItem("1",1);
    portCom->addItem("2",2);
    portCom->addItem("3",3);
    portCom->addItem("4",4);
    portCom->addItem("5",5);
    portCom->addItem("6",6);
    portCom->addItem("7",7);
    portCom->addItem("8",8);
    
    baudRate->addItem("4800",4800);
    baudRate->addItem("9600",9600);
    baudRate->addItem("19200",19200);
    baudRate->addItem("38400",38400);
    baudRate->addItem("57600",57600);
    
    dataLength->addItem("5",5);
    dataLength->addItem("6",6);
    dataLength->addItem("7",7);
    dataLength->addItem("8",8);
    
    parity->addItem("None","None");
    parity->addItem("Even","Even");
    parity->addItem("Odd","Odd");
    
    stopBit->addItem("1",1);
    stopBit->addItem("2",2);
    
    saveConfigButton = new QPushButton(tr("Save Configuration"));
    
    QGridLayout *updateLayout = new QGridLayout;
    updateLayout->addWidget(pComLabel,0,0);
    updateLayout->addWidget(portCom,0,1);
    updateLayout->addWidget(pBaudLabel,1,0);
    updateLayout->addWidget(baudRate,1,1);
    updateLayout->addWidget(pDataLabel,2,0);
    updateLayout->addWidget(dataLength,2,1);
    updateLayout->addWidget(pParLabel,3,0);
    updateLayout->addWidget(parity,3,1);
    updateLayout->addWidget(pStopLabel,4,0);
    updateLayout->addWidget(stopBit,4,1);
    rs232ConfigGroup->setLayout(updateLayout);
    
    QVBoxLayout *mainLayout = new QVBoxLayout;
    mainLayout->addWidget(rs232ConfigGroup);
    mainLayout->addWidget(rs232ConfigGroup);
    mainLayout->addSpacing(12);
    mainLayout->addWidget(saveConfigButton);
    mainLayout->addStretch(1);
    setLayout(mainLayout);
    
    connect(saveConfigButton, SIGNAL(clicked()), this, SLOT(SaveConfigParameters())); // here is my problem
    

    }

    void ConfigRS232::SaveConfigParameters()
    {
    _portCom = portCom->currentIndex();
    _baudRate = baudRate->currentIndex();
    _dataLength = dataLength->currentIndex();
    _parity = parity->currentIndex();
    _stopBit = stopBit->currentIndex();

    cout << endl << "Port Com # : " << _portCom << endl;
    

    }@

    Just for more precisions, I tried without instanciate Q_OBJECT in the .h file but it doesn’t connect my pushbutton with my slot (SaveConfigParameters) …

    Somebody have an idea ?


  • Sounds like an include problem, even if it is not clear without the exact error. Does it work if you include each single widget you use in the header file?


  • I think the problem is about the instanciation of the parent class… So I tried your suggestion but the error still the same :

    @./debugconfigrs232.o: In function ConfigRS232': C:Documents and Settingslouis_fournierMes documentsProjetQtAPI_A429_ProjectAPI_A429-build-desktop-Qt_4_7_4_for_Desktop_-_MinGW_4_4__Qt_SDK__Debug/../API_A429/configrs232.cpp:7: undefined reference tovtable for ConfigRS232′
    C:Documents and Settingslouis_fournierMes documentsProjetQtAPI_A429_ProjectAPI_A429-build-desktop-Qt_4_7_4_for_Desktop_-MinGW_4_4__Qt_SDK__Debug/../API_A429/configrs232.cpp:7: undefined reference to vtable for ConfigRS232' C:Documents and Settingslouis_fournierMes documentsProjetQtAPI_A429_ProjectAPI_A429-build-desktop-Qt_4_7_4_for_Desktop_-_MinGW_4_4__Qt_SDK__Debug/../API_A429/configrs232.cpp:7: undefined reference tovtable for ConfigRS232′
    C:Documents and Settingslouis_fournierMes documentsProjetQtAPI_A429_ProjectAPI_A429-build-desktop-Qt_4_7_4_for_Desktop
    -_MinGW_4_4__Qt_SDK__Debug/../API_A429/configrs232.cpp:7: undefined reference to vtable for ConfigRS232' ./debugconfigrs232.o:C:Documents and Settingslouis_fournierMes documentsProjetQtAPI_A429_ProjectAPI_A429-build-desktop-Qt_4_7_4_for_Desktop_-_MinGW_4_4__Qt_SDK__Debug/../API_A429//configrs232.h:9: undefined reference toConfigRS232::staticMetaObject’
    collect2: ld returned 1 exit status
    mingw32-make[1]: *** [debugAPI_A429.exe] Error 1
    mingw32-make: *** [debug] Error 2
    Le processus «D:QtSDKmingwbinmingw32-make.exe» s’est terminé avec le code 2.
    Erreur à la compilation du projet API_A429 (cible : Desktop)
    Lors de l’exécution de l’étape «Make»@

    So here it’s my HEADER file :
    @#ifndef CONFIGRS232_H
    #define CONFIGRS232_H

    #include <QtGui>
    #include <QWidget>

    class ConfigRS232: public QWidget
    {
    Q_OBJECT

    QComboBox *portCom;
    QComboBox *baudRate;
    QComboBox *dataLength;
    QComboBox *parity;
    QComboBox *stopBit;
    
    QLabel *pComLabel;
    QLabel *pBaudLabel;
    QLabel *pDataLabel;
    QLabel *pParLabel;
    QLabel *pStopLabel;
    
    QGroupBox *rs232ConfigGroup;
    
    QGridLayout *updateLayout;
    QVBoxLayout *mainLayout;
    
    QPushButton *saveConfigButton;
    

    public:
    ConfigRS232(QWidget *parent = 0);

    private:
    int _portCom;
    int _baudRate;
    int _dataLength;
    int _parity;
    int _stopBit;

    public slots:
    void SaveConfigParameters();
    };

    #endif // CONFIGRS232_H@

    And the CPP file:
    @#include «configrs232.h»

    #include <iostream>
    using namespace std;

    ConfigRS232::ConfigRS232(QWidget *parent)
    : QWidget(parent)
    {
    rs232ConfigGroup = new QGroupBox(tr(«RS232 Configuration»));

    pComLabel = new QLabel(tr("Com Port #"));
    portCom = new QComboBox;
    pBaudLabel = new QLabel(tr("Bite Rate (bps):"));
    baudRate = new QComboBox;
    pDataLabel = new QLabel(tr("Data Length:"));
    dataLength = new QComboBox;
    pParLabel = new QLabel(tr("Parity:"));
    parity = new QComboBox;
    pStopLabel = new QLabel(tr("Stop Bit:"));
    stopBit = new QComboBox;
    
    portCom->addItem("1",1);
    portCom->addItem("2",2);
    portCom->addItem("3",3);
    portCom->addItem("4",4);
    portCom->addItem("5",5);
    portCom->addItem("6",6);
    portCom->addItem("7",7);
    portCom->addItem("8",8);
    
    baudRate->addItem("4800",4800);
    baudRate->addItem("9600",9600);
    baudRate->addItem("19200",19200);
    baudRate->addItem("38400",38400);
    baudRate->addItem("57600",57600);
    
    dataLength->addItem("5",5);
    dataLength->addItem("6",6);
    dataLength->addItem("7",7);
    dataLength->addItem("8",8);
    
    parity->addItem("None","None");
    parity->addItem("Even","Even");
    parity->addItem("Odd","Odd");
    
    stopBit->addItem("1",1);
    stopBit->addItem("2",2);
    
    saveConfigButton = new QPushButton(tr("Save Configuration"));
    
    updateLayout = new QGridLayout;
    updateLayout->addWidget(pComLabel,0,0);
    updateLayout->addWidget(portCom,0,1);
    updateLayout->addWidget(pBaudLabel,1,0);
    updateLayout->addWidget(baudRate,1,1);
    updateLayout->addWidget(pDataLabel,2,0);
    updateLayout->addWidget(dataLength,2,1);
    updateLayout->addWidget(pParLabel,3,0);
    updateLayout->addWidget(parity,3,1);
    updateLayout->addWidget(pStopLabel,4,0);
    updateLayout->addWidget(stopBit,4,1);
    rs232ConfigGroup->setLayout(updateLayout);
    
    mainLayout = new QVBoxLayout;
    mainLayout->addWidget(rs232ConfigGroup);
    mainLayout->addWidget(rs232ConfigGroup);
    mainLayout->addSpacing(12);
    mainLayout->addWidget(saveConfigButton);
    mainLayout->addStretch(1);
    setLayout(mainLayout);
    
    connect(saveConfigButton, SIGNAL(clicked()), this, SLOT(SaveConfigParameters()));
    

    }

    void ConfigRS232::SaveConfigParameters()
    {
    _portCom = portCom->currentIndex();
    _baudRate = baudRate->currentIndex();
    _dataLength = dataLength->currentIndex();
    _parity = parity->currentIndex();
    _stopBit = stopBit->currentIndex();

    cout << endl << "Port Com # : " << _portCom << endl;
    

    }@


  • The above code is running perfectly for me. Couldn’t reproduce the issue.

    bq. I tried without instanciate Q_OBJECT in the .h file

    You need Q_OBJECT macro, so that MOC (meta Object Compiler) will do the necessary to implement signals and slots . Refer «Meta-Object system»:http://doc.qt.nokia.com/4.7/metaobjects.html#meta-object-system

    Late relpy : i meant the first post.


  • Try rebuilding your project (just remove the build directory). It is a moc issue


  • Such problems are usually solved by (manually) re-running qmake.


  • Oh great, you’re right, I deleted the build folder and that’s work pretty good !! I don’t really know why it doesn’t work at the first time, the MOC is the pre-compiled processor instructions ?


  • No, moc is the «Meta-Object Compiler»:http://doc.qt.nokia.com/latest/moc.html.


  • Ok thanks, I just have two more questions …

    1. Do you know how can I get some values of a QComboBox (I tried with currentIndex() function and currentText but it doesn’t really works…)

    2. Which project can let me generate an application but without Qt development tool (like .exe and can be ran without problems…)

    Anyway, I appreciate your help

    PS: I’m a beginner with Qt …


    • currentIndex() and currentText() is the way to go. If they return invalid data there is most probably no item selected or the combo box is empty.
    • Every single Application type (Qt Quick Application, Qt Gui Application, Mobile Qt Application, …) generates a standalone binary (.exe). But you will have to distribute — as with every other non-Qt application — the «runtime dependencies»:http://doc.qt.nokia.com/latest/deployment-windows.html along with your application.

  • In addition you can try compiling statically. so that every libraries and dependencies packed into a single executable.

    «Ref»:http://doc.qt.nokia.com/stable/deployment.html


  • Thanks a lot guys! You’re getting me out of every problems and I appreciate it !!


  • You’re welcome 🙂 Happy coding 🙂


  • It may happen if you change file path and header and cpp files has different paths


  • ?

    LiveJournal

    Log in

    If this type of authorization does not work for you, convert your account using the link

    September 19 2013, 21:02

    Category:

    • IT
    • Cancel

    Тысячу и один раз это отвечено на stackoverflow, и в тысячу и один раз начинается тупак под вечер, когда не удается вспомнить все возможные причины. Итак, причины error: undefined reference to `vtable и пути их решения:

    1. Класс унаследовал чистые виртуальные функции и не переопределил их. Определите их.
    2. Класс был объявлен наследником QObject с макросом Q_OBJECT после moc-а. Сделайте moc заново.
    3. Заголовочный файл не включен в проект или был включен до появления в нём Q_OBJECT-а. Пересоберите проект, либо (короткий путь) обновите таймштамп файла проекта и сделайте Build.
      Например, быстрый способ обновить таймштампы всех подпроектов:
      # find . -name '*.pro' -exec touch '{}' ;
    4. Макрос Q_OBJECT используется не в заголовочном файле. Нужно добавить #include "<BASENAME>.moc" в исходник, это укажет qmake-у выполнить moc для этого файла, чтобы сгенерировать код для QObject-а (сигналы/слоты и т.д.). Поместить #include «<BASENAME>.moc» нужно просто в конце файла <BASENAME>.cpp и затем пересобрать проект.
      За этот пункт спасибо ответу в вопросе http://stackoverflow.com/questions/21729769/why-is-vtable-linking-issue-while-adding-javascript-window-object.

    И отдыхайте чаще. Во всех случаях.

    0 0 голоса
    Рейтинг статьи
    Подписаться
    Уведомить о
    guest

    0 комментариев
    Старые
    Новые Популярные
    Межтекстовые Отзывы
    Посмотреть все комментарии

    А вот еще интересные материалы:

  • Яшка сломя голову остановился исправьте ошибки
  • Ясность цели позволяет целеустремленно добиваться намеченного исправьте ошибки
  • Ясность цели позволяет целеустремленно добиваться намеченного где ошибка
  • Undefined near line 1 column 1 octave ошибка
  • Undefined is not a function ошибка