19

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?

Aquarius_Girl
  • 21,790
  • 65
  • 230
  • 411
  • I don't see what is the problem, but I would like to point out that the tutorial you are using is rather outdated. I suggest you look at the tutorials in Qt 4.7 documentation. – ypnos May 02 '11 at 08:11
  • @ypnos thanks but the tut on 4.7 doesn't show any "running" example, which I could just paste and run :( – Aquarius_Girl May 02 '11 at 08:28
  • Possible duplicate of [Qt moc with implementations inside of header files?](http://stackoverflow.com/questions/3001615/qt-moc-with-implementations-inside-of-header-files) – Stefan Monov Jan 05 '17 at 17:27
  • Possible duplicate of [Undefined reference to vtable. Trying to compile a Qt project](https://stackoverflow.com/questions/1552069/undefined-reference-to-vtable-trying-to-compile-a-qt-project) – iammilind Jun 14 '17 at 10:57

5 Answers5

36

It looks like moc doesn't generate code for your QObject because you declare it in the .cpp file. The easiest way to fix that is to move the declaration of MyWindow to a header, and add the header to the HEADERS list, in the .pro file:

HEADERS += yourheader.h 

Then rerun qmake.

(Please note that the KDE 2.0 book you look at is vastly outdated)

Itay Grudev
  • 7,055
  • 4
  • 54
  • 86
Frank Osterfeld
  • 24,815
  • 5
  • 58
  • 70
  • Thanks for responding, but is there no way by which I can keep the declaration and the definition in the .cpp file? – Aquarius_Girl May 02 '11 at 08:16
  • Try with HEADERS += your.cpp . Generally, although possible, I find QObject declarations so much pain that I prefer to have them (private) headers instead. Which works fine with all buildsystems, be it qmake, cmake, ... – Frank Osterfeld May 02 '11 at 08:21
  • Thanks again, I seperated the .h, .cpp and main :mad: and it solved the error, I haven't yet studied details regarding moc file. – Aquarius_Girl May 02 '11 at 08:27
  • 17
    Whenever you declare a QObject inside a filename.cpp file, you should add `#include "filename.moc"` to the end of your .cpp file and qmake will do the right thing for you. This is the common practice in KDE, for example. – andref May 02 '11 at 14:24
  • Excellent answer. It's annoying that Qt imposes extra limitations above C++ itself but I guess I can live with that. – paxdiablo Aug 01 '16 at 05:24
23

Maybe too late but... Had the same issue and fighted for a while to find where it comes from.

Right click on your project and select “Run qmake” to for a new build of MOC classes. It usually does run automatically...

The moc compiler generates the stubs and calls in moc_xxxx.cpp, and generates the vtable stuff

sylvain
  • 231
  • 2
  • 2
1

Based on andref comment just above, when everything is in one cpp file like stuff.cpp, you need to add at the end of the file:

#include "moc_stuff.cpp"

(this is with Qt 4.7.0)

calandoa
  • 5,668
  • 2
  • 28
  • 25
1

Just Change your Main() as follows:

#include <QtGui/QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MyWindow w;

    w.show();

    return a.exec();
}
RvdK
  • 19,580
  • 4
  • 64
  • 107
anj
  • 355
  • 2
  • 5
  • 20
0

This issue may be caused by some of the following reasons. I have stumbled on all of them from time to time.


Your class header may be missing the Q_OBJECT macro. Add the macro to the header as already noted by other answers.

class MyWidg : public QWidget
{
    Q_OBJECT

Your class header may not be parsed by the moc. Add the header file in the HEADERS definitions of your .pro (or .pri) project file.

HEADERS += file.h

If none of the above is true, then you probably need to run qmake again to make sure moc parses the header again, just in case the Q_OBJECT macro was added in the header after the qmake was run. Just run qmake again.

kotsos
  • 1
  • 1