This question already has answers here:
Qt Linker Error: "undefined reference to vtable" [duplicate]
(9 answers)
Closed 9 years ago.
When I uncomment the Q_OBJECT macro that I need for signal-slot I get a undefined reference to vtable for MyApp error, but without the macro it compiles perfectly but I can't use signals and slots without it. I think I may be doing something stupid wrong, but please try helping because I realy can't find the problem. O and I know my code is untidy and am working on it.
myapp.h:
#ifndef MYAPP_H
#define MYAPP_H
#include <QApplication>
#include <QEvent>
#include <QObject>
#include <QDebug>
class MyApp : public QApplication
{
public:
MyApp( int argc, char** argv );
protected:
bool eventFilter(QObject *object, QEvent *event);
signals:
void focusG();
void focusL();
};
#endif // MYAPP_H
myapp.cpp:
#include "myapp.h"
MyApp::MyApp(int argc, char **argv): QApplication(argc, argv)
{
installEventFilter(this);
}
bool MyApp::eventFilter(QObject *object, QEvent *event)
{
if (event->type() == QEvent::ApplicationDeactivate)
{
qDebug() << "Focus lost";
//focusL();
}
if (event->type() == QEvent::ApplicationActivate)
{
qDebug() << "Focus gained";
//focusG();
}
return false;
}
main.cpp:
#include <QtGui/QApplication>
#include "qmlapplicationviewer.h"
#include <QObject>
#include <QGraphicsObject>
#include <QTimer>
#include <QVariant>
#include "timecontrol.h"
#include "scorecontrol.h"
#include "Retry.h"
#include <QEvent>
#include "myapp.h"
int main(int argc, char *argv[])
{
//QApplication app(argc, argv);
MyApp app(argc, argv);
QmlApplicationViewer viewer;
viewer.setOrientation(QmlApplicationViewer::ScreenOrientationLockLandscape);
viewer.setMainQmlFile(QLatin1String("qml/Raker/main.qml"));
viewer.showExpanded();
QObject *rootObject = viewer.rootObject();
QTimer *timmer = new QTimer;
timmer->setInterval(1000);
TimeControl *timcon = new TimeControl;
scorecontrol *scorer = new scorecontrol;
Retry *probeer = new Retry;
QObject::connect(timmer, SIGNAL(timeout()), timcon, SLOT(updateTime()));
QObject::connect(timcon, SIGNAL(setTime(QVariant)), rootObject, SLOT(setTime(QVariant)));
QObject::connect(rootObject, SIGNAL(blockClicked(int, int)), scorer, SLOT(checkRight(int, int)));
QObject::connect(scorer, SIGNAL(setScore(QVariant)), rootObject, SLOT(setScore(QVariant)));
QObject::connect(scorer, SIGNAL(setState(QVariant)), rootObject, SLOT(setState(QVariant)));
QObject::connect(rootObject, SIGNAL(start()), probeer, SLOT(Reetry()));
QObject::connect(probeer, SIGNAL(start()), timmer, SLOT(start()));
QObject::connect(probeer, SIGNAL(stop()), timmer, SLOT(stop()));
QObject::connect(probeer, SIGNAL(start(int)), scorer, SLOT(randomNum(int)));
QObject::connect(probeer, SIGNAL(sReset()), timcon, SLOT(reset()));
QObject::connect(probeer, SIGNAL(tReset()), scorer, SLOT(reset()));
QObject::connect(timcon, SIGNAL(timeOut()), scorer, SLOT(reset()));
QObject::connect(timcon, SIGNAL(setState(QVariant)), rootObject, SLOT(setState(QVariant)));
QObject::connect(timcon, SIGNAL(changeFinal()), scorer, SLOT(changeFinal()));
QObject::connect(scorer, SIGNAL(setFinal(QVariant)), rootObject, SLOT(setFinal(QVariant)));
QObject::connect(&app, SIGNAL(focusL()), probeer, SLOT(focusL()));
QObject::connect(&app, SIGNAL(focusG()), probeer, SLOT(focusG()));
return app.exec();
}
BlockToucher.pro:
# Add more folders to ship with the application, here
folder_01.source = qml/Raker
folder_01.target = qml
DEPLOYMENTFOLDERS = folder_01
# Additional import path used to resolve QML modules in Creator's code model
QML_IMPORT_PATH =
symbian:TARGET.UID3 = 0x2004b49f
# Smart Installer package's UID
# This UID is from the protected range and therefore the package will
# fail to install if self-signed. By default qmake uses the unprotected
# range value if unprotected UID is defined for the application and
# 0x2002CCCF value if protected UID is given to the application
symbian:DEPLOYMENT.installer_header = 0x2002CCCF
# Allow network access on Symbian
symbian {
#TARGET.CAPABILITY += NetworkServices
vendorinfo = "%{\"Gerhard de Clercq\"}" ":\"Gerhard de Clercq\""
ICON = BlockToucher.svg
}
# If your application uses the Qt Mobility libraries, uncomment the following
# lines and add the respective components to the MOBILITY variable.
# CONFIG += mobility
# MOBILITY +=
# The .cpp file which was generated for your project. Feel free to hack it.
SOURCES += main.cpp \
timecontrol.cpp \
scorecontrol.cpp \
Retry.cpp \
myapp.cpp \
myapplication.cpp
# Please do not modify the following two lines. Required for deployment.
include(qmlapplicationviewer/qmlapplicationviewer.pri)
qtcAddDeployment()
HEADERS += \
timecontrol.h \
scorecontrol.h \
Retry.h \
myapp.h \
myapplication.h
OTHER_FILES += \
qtc_packaging/debian_fremantle/rules \
qtc_packaging/debian_fremantle/README \
qtc_packaging/debian_fremantle/copyright \
qtc_packaging/debian_fremantle/control \
qtc_packaging/debian_fremantle/compat \
qtc_packaging/debian_fremantle/changelog
compat \
qtc_packaging/debian_fremantle/changelog
Q_OBJECT is used by the MOC system to produce the code you need for the signals. My best guess would be that you are not included the MOC generated files in your project (the CPP files which it generates).
How you do this greatly depends on your build system (CMake, QMake, AUtomake, MSVC) but you should refer to the tutorial with QMake first.
That is, the undefined reference to vtable is the error I sometimes get when I forget to update my Cmake files and have a Q_OBJECT.
Also, your ctor for MyApp is wrong, the signature must be:
MyApp( int & argc, char** argv );
The & is important should you ever use command-line parameters.
I had same issue when i decided to add Q_OBJECT into my header file.
First try run qmake manually.
If not resolved, so delete build folder and build project again
If building all of the project is a heavy task, so try following steps:
Add a new temp class with QObject as its base class
Double check your header and source file for any mistake using new temp class
Build your project. It should built successfully
Remove your temp class completely (.h and .cpp file and relative lines on .pro file)
Good luck :)
Related
I am trying follow the instructions published here:
https://www.linux.org/threads/c-tutorial-create-qt-applications-without-qtcreator.18409/
but in a PC running Windows 10, to build a Qt application createdwith the Atom editor. I have this 3 files in my project right now:
qt_main.cpp
#include <QtWidgets>
#include "mainwidget.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWidget w;
w.show();
return a.exec();
}
mainwidget.h
#ifndef MAINWIDGET_H
#define MAINWIDGET_H
#include <QWidget>
class QPushButton;
class QTextBrowser;
class MainWidget : public QWidget
{
Q_OBJECT
public:
explicit MainWidget(QWidget *parent = 0);
~MainWidget();
private:
QPushButton* button_;
QTextBrowser* textBrowser_;
};
#endif // MAINWIDGET_H
mainwidget.cpp
#include <QtWidgets>
#include "mainwidget.h"
MainWidget::MainWidget(QWidget *parent) : QWidget(parent)
{
button_ = new QPushButton(tr("Push Me!"));
textBrowser_ = new QTextBrowser();
QGridLayout *mainLayout = new QGridLayout;
mainLayout->addWidget(button_,0,0);
mainLayout->addWidget(textBrowser_,1,0);
setLayout(mainLayout);
setWindowTitle(tr("Connecting buttons to processes.."));
}
MainWidget::~MainWidget()
{
delete button_;
delete textBrowser_;
}
I execute this commands, in sequence:
qmake -project
add `QT += widgets` to the qt_main.pro file generated
qmake qt_main.pro
make
After that, the EXE file is generated without error, but when I try run it, I got the error:
"The procedure entry point _ZN10QArrayData10deallocateEPS_jj could not be located in the dynamic link library etc."
I try follow the suggested on the comments for the question:
QArrayData error, linking Qt libraries with CMake
and check my PATH. right now, the only directory containing qt DLLs is the one:
C:\Qt\Qt5.14.0\5.14.0\mingw73_64\bin
(this directory was createwd by the Qt offline installer).
Anyone can give a hint of how to solve this issue?
I have naturally trivial question as I mean: we press button --> counter increases, counter increases --> QLabel's value is renewed. I caught strange error and don't want to do. I'm not dummy in C++ but in QT I am. It's my first and most trivial application in it.
Some answers there (on Stack Overflow) advised to add virtual constructor. It has no effect.
I tried to rewrite signals and slots to new qt5 style but there were another problems, I was too lazy to fix them, was it (rewriting, not laziness :) ) a good way, maybe problem is really with versions?
I just haven't tried to reinstall QT or install Qt4, maybe problem is in it?
about versions:
$ qmake --version
responds:
QMake version 3.0
Using Qt version 5.5.1 in /usr/lib/x86_64-linux-gnu
conn.pro:
TEMPLATE = app
QT += core gui
TARGET = conn
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
SOURCES += main.cpp
main.cpp:
#include <QApplication>
#include <QLabel>
#include <QPushButton>
#include <QObject>
class Counter : public QObject {
Q_OBJECT
private:
double i_;
public:
virtual ~Counter()
{
}
Counter() : QObject(), i_(0)
{
}
public slots:
void slot_incCounter();
signals:
void goodbye(){}
void counterChanged(double){}
};
void Counter::slot_incCounter() {
emit counterChanged(++i_);
if (i_ == 5) {
emit goodbye();
}
}
int main(int argc, char* argv[]) {
QApplication my_app(argc, argv);
QLabel label1("label i created");
label1.show();
QPushButton button1("press me");
button1.show();
Counter counter1;
QObject::connect(&button1, SIGNAL(clicked()),
&counter1, SLOT(slot_incCounter()));
QObject::connect(&counter1, SIGNAL(counterChanged(double a)),
&label1, SLOT(setNum(double a)));
QObject::connect(&counter1, SIGNAL(goodbye()),
&my_app, SLOT(quit()));
return my_app.exec();
}
Try to run it:
qmake && make && ./conn
So I see in console:
g++ -m64 -Wl,-O1 -o conn main.o -L/usr/X11R6/lib64 -lQt5Widgets -lQt5Gui -lQt5Core -lGL -lpthread
main.o: In function `main':
main.cpp:(.text.startup+0xd6): undefined reference to `vtable for Counter'
collect2: error: ld returned 1 exit status
Makefile:144: recipe for target 'conn' failed
make`:` *** [conn] Error 1
What should I do?
Qt uses the meta object compiler (moc) to enable e.g. signal and slots. By default it works perfectly if the Q_OBJECT macro is in a header file. So the easiest would be you put Counter into it's own header/implementation file, rerun qmake and make. (That's by the way good practice...)
If you want to stick with a single main.cpp file you need to tell the moc explicitly that this file contains macros moc needs to parse. You do this with the following line at the very end of main.cpp:
#include "main.moc"
Then also rerun qmake and make.
Please keep in mind that the manually including a moc-include directive is not the best choice. So better split your C++ classes into separate files right from the beginning...
Thank you very much! Your answer was full, useful and making all more obvious.
Solution was:
1. Move class Counter to Counter.h
Since this moment the message about vtable disappeared. Appeared messages that goodbye() and Counter::counterChanged(double) have multiple definition. The first definition was mine in Counter.cpp (WRONG WAY). The second was in moc_Counter.cpp, generated by MOC utility. So:
2. Remove definitions (my empty definitions) of signal functions, because moc makes its own in file moc_Counter.cpp:
// SIGNAL 0
void Counter::goodbye()
{
QMetaObject::activate(this, &staticMetaObject, 0, Q_NULLPTR);
}
// SIGNAL 1
void Counter::counterChanged(double _t1)
{
void *_a[] = { Q_NULLPTR, const_cast<void*>(reinterpret_cast<const void*>(&_t1)) };
QMetaObject::activate(this, &staticMetaObject, 1, _a);
}
and they cause a problem of multiple definition.
Summing it up, working code:
main.cpp:
#include <QApplication>
#include "Counter.h"
int main(int argc, char* argv[]) {
QApplication my_app(argc, argv);
QLabel label1("1");
label1.show();
QPushButton button1("press me");
button1.show();
Counter counter1;
QObject::connect(&button1, SIGNAL(clicked()),
&counter1, SLOT(slot_incCounter()));
QObject::connect(&counter1, SIGNAL(counterChanged(double)),
&label1, SLOT(setNum(double)));
QObject::connect(&counter1, SIGNAL(goodbye()),
&my_app, SLOT(quit()));
return my_app.exec();
}
void Counter::slot_incCounter() {
emit counterChanged(++i_);
if (i_ == 5) {
emit goodbye();
}
}
Counter.h:
#ifndef COUNTER_H
#define COUNTER_H
#include <QLabel>
#include <QPushButton>
#include <QObject>
class Counter : public QObject {
Q_OBJECT
private:
double i_;
public:
virtual ~Counter()
{
}
Counter() : QObject()
{
}
public slots:
void slot_incCounter();
signals:
void goodbye();
void counterChanged(double);
};
#endif // COUNTER_H
Counter.cpp:
#include "Counter.h"
Thank you, you're great!
When I try to compile my program I get the error
obj/backgroundWorker.o: In function `BackgroundWorker':
.../backgroundWorker.cpp:6: undefined reference to `vtable for BackgroundWorker'
obj/backgroundWorker.o: In function `~BackgroundWorker':
.../backgroundWorker.cpp:14: undefined reference to `vtable for BackgroundWorker'
I already found numerous reasons for this error, but so far, I couldn't
solve the problem in my code:
backgroundWorker.hpp
#include <QObject>
#include <QPushButton>
class BackgroundWorker : public QWidget{
Q_OBJECT
public:
explicit BackgroundWorker();
~BackgroundWorker();
private slots:
void start();
private:
QPushButton* mStartButton;
};
backgroundWorker.cpp
#include <iostream>
#include "getInput.hpp"
#include "backgroundWorker.hpp"
#include "LIF_network.hpp"
BackgroundWorker::BackgroundWorker(){
mStartButton = new QPushButton("Start",this);
mStartButton->setGeometry(QRect(QPoint(100,100),QSize(200,50)));
connect(mStartButton, SIGNAL(released()), this, SLOT(start()));
}
BackgroundWorker::~BackgroundWorker(){
delete mStartButton;
}
void BackgroundWorker::start(){
//stuff not related to qt
}
main.cpp
#include <QApplication>
#include "backgroundWorker.hpp"
int main(int argc, char *argv[]){
QApplication a(argc, argv);
BackgroundWorker bw;
return a.exec();
}
** .pro file**
CONFIG += qt debug c++11
QT += widgets
QMAKE_CC = clang++
QMAKE_CXX = clang++
QMAKE_CXXFLAGS += -Wall -Werror -O3
Headers += image.hpp \
getInput.hpp \
LIF_network.hpp \
backgroundWorker.hpp \
SOURCES += main.cpp \
image.cpp \
getInput.cpp \
LIF_network.cpp \
backgroundWorker.cpp \
OBJECTS_DIR = ./obj
As Frank Osterfeld mentioned in the comment the proper name for the variable is upper case HEADERS. And it should contain the list of all headers that have Q_OBJECT macro in them
This is required because qmake needs to know the list of header files to feed to the moc.
I have already posted this in the OSG mailing list, but the mailing list seems to be a bit slow.
Anyway, I'm trying to modify the osgViewerQt example by adding a new class of my
own that will contain the viewer. The design is:
wrapper.h: Defines class Wrapper. It inherits from
QMainWindow and has a
QDockWidget where the ViewerWidget will be attached.
viewer.h: Defines ViewerWidget class. It's the class from the
example, with a few mods by me.
prueba_qt.cpp: Main function and where a QApplication is created. A Wrapper object is
created here.
The project compiles, but when I execute it, I get an error:
QWidget: Must construct a QApplication before a QPaintDevice*
If I remove the Q_OBJECT line, the signal and the slot from
wrapper.h and compile the files from the terminal using
g++ -IE:/osg-3.0.1/install/include -LE:/osg-3.0.1/install/bin -IC:/Qt64/4.8/include -LC:/Qt64/4.8/bin -losgViewer -lOpenThreads -losgDB -losg -losgGA -losgQt -lQtCore4 -lQtGui4 prueba_qt.cpp
I can execute the app.
Can you please tell me what can I do to make this work? I've struggling all
morning but couldn't find the solution.
Thanks for your time!
PS: SO is Windows 7 64 bits # MingW compiler # Qt 4.8 # OSG 3.0.1
PS2: Here're the files I used in this project, including the pro file from qmake:
wrapper.h
#ifndef Wrapper_hpp
#define Wrapper_hpp
#include "viewer.h"
#include <QtGui/QMainWindow>
#include <QtGui/QDockWidget>
class Wrapper: public QMainWindow {
Q_OBJECT
private:
ViewerWidget* view;
QDockWidget* dock;
public:
Wrapper(void) {
view = new ViewerWidget();
dock = new QDockWidget;
dock->setWidget( view );
dock->setGeometry( 100, 100, 800, 600 );
dock->setAllowedAreas(Qt::RightDockWidgetArea);
addDockWidget(Qt::RightDockWidgetArea, dock);
dock->show();
}
void Do(void) { view->Do(); }
void Add(void) { view->Add(); }
virtual ~Wrapper(void) {}
public slots:
void MySlot(void) {}
signals:
void MySignal(void);
};
#endif
wrapper.cpp
(This exists only because I read in the Qt forum that moc can only parse cpp files and thus one is needed for the signal/slot mechanism.)
#include "wrapper.h"
Wrapper::Wrapper(void) {
view = new ViewerWidget();
// view->setGeometry( 100, 100, 800, 600 );
dock = new QDockWidget;
dock->setWidget( view );
dock->setGeometry( 100, 100, 800, 600 );
dock->setAllowedAreas(Qt::RightDockWidgetArea);
addDockWidget(Qt::RightDockWidgetArea, dock);
dock->show();
}
prueba_qt.cpp
#include <QtGui/QApplication>
#include <iostream>
#include "wrapper.h"
int main( int argc, char** argv ) {
osg::ArgumentParser arguments(&argc, argv);
QApplication app(argc, argv);
Wrapper wrap;
wrap.resize(800,600);
wrap.setWindowTitle("Cow");
wrap.showNormal();
wrap.Do();
return app.exec();
}
prueba_qt.pro
######################################################################
# Automatically generated by qmake (2.01a) mar 12. mar 13:45:28 2013
######################################################################
QT += core gui
TEMPLATE = app
TARGET =
DEPENDPATH += .
INCLUDEPATH += . E:/osg-3.0.1/install/include
LIBS += -LE:/osg-3.0.1/install/bin -losg -lOpenThreads -losgDB -losgGA -losgQt -losgViewer
# Input
HEADERS += viewer.h wrapper.h
SOURCES += prueba_qt.cpp wrapper.cpp
viewer.h: This is quite big, so I uploaded it to pastebin
EDIT #1
I have set OSG_NOTIFY_LEVEL to DEBUG_INFO and got this humongous output. The line with the error is:
FindFileInPath() : trying C:\cygwin\bin\osgPlugQWidget: Must construct a QApplication before a QPaintDevice
EDIT #2
The signal and slot were missing in the code. I have just added them to wrapper.h along with the call to Q_OBJECT.
After a little nap, I revised again the libraries used in the project. The problem was that some of those libraries were in debug mode and some in release mode. When using signals and slots, moc went crazy.
After building OSG debug libraries, I tried again my little example and worked.
So it's done!
I must be missing a basic concept with headers and includes because when I attempt to call even the simplest of a function from a separate source file I get an error:
main.obj:-1: error: LNK2019: unresolved external symbol "void __cdecl
buildDeck(int,int)" (?buildDeck##YAXHH#Z) referenced in function _main
deck.h
#ifndef DECK_H
#define DECK_H
#include <QString>
void buildDeck(int deckSize, int jokers);
struct card
{
QString suit;
QString color;
int rank;
};
#endif // DECK_H
deck.cpp
#include"mainwindow.h"
#include "deck.h"
void buildDeck(int deckSize, int jokers)
{
int blackRed = deckSize-=jokers;
}
main.cpp
#include "mainwindow.h"
#include "deck.h"
#include <QApplication>
#include <QPushButton>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
buildDeck(10,20);
return a.exec();
}
And this gives me an error. However, If I move the function definition from deck.cpp to the bottom of main.cpp, then the application will build.
All of the files are included in the same project, and stored in the same directory.
Other files:
.pro file
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = carddeck
TEMPLATE = app
SOURCES += main.cpp\
mainwindow.cpp \
deck.cpp
HEADERS += mainwindow.h \
deck.h
FORMS += mainwindow.ui
not sure if you need it, but here's mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QPushButton>
#include <QTextEdit>
#include <QCheckBox>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
void runButtonClicked();
private:
Ui::MainWindow *ui;
QPushButton *runButton;
QTextEdit * runText;
QCheckBox * betHearts;
QCheckBox * betDiamonds ;
QCheckBox * betClubs;
QCheckBox * betSpades ;
QCheckBox * betFlush ;
QCheckBox * betAllRed;
QCheckBox * betAllBlack ;
};
#endif // MAINWINDOW_H
It looks like the Makefile was not regenerated when you edited the .pro file.
Run qmake and try again.
You could also check if the deck.cpp is compiled or not; is there a deck.o in the build directory ?
yes, some time Makefile file is not updated while you change .pro file. So you have to run qmake.
Follow this steps:
Right click on project Clean / Build menu -> cleanAll
Right click on project Run qmake / Build menu -> runQmake
Right click on project Build / Build menu -> build
Pro Advice:
I don't know but sometime Qt is not updating Makefile. so i recomanded to all whenever you add/removing any resource in project or if any changes occur in your .pro file, just Run qmake and build your project(Running qmake do manually to update the path of project, which help to find the mainwindow.obj file).