3

Possible Duplicate:
Qt: Signals and slots Error: undefined reference to `vtable for

Here we have test.cpp:

#include <QApplication>
#include <QMainWindow>

class MainWindow : public QMainWindow
{
    Q_OBJECT
};

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

    return a.exec();
}

Place alone in a new directory and:

$ qmake -project
$ qmake
$ make

It doesn't work:

test.o: In function `MainWindow::~MainWindow()':
test.cpp:(.text._ZN10MainWindowD2Ev[_ZN10MainWindowD5Ev]+0x3): undefined reference to `vtable for MainWindow'
test.cpp:(.text._ZN10MainWindowD2Ev[_ZN10MainWindowD5Ev]+0xb): undefined reference to `vtable for MainWindow'
test.o: In function `main':
test.cpp:(.text.startup+0x48): undefined reference to `vtable for MainWindow'
test.cpp:(.text.startup+0x51): undefined reference to `vtable for MainWindow'
test.o: In function `MainWindow::~MainWindow()':
test.cpp:(.text._ZN10MainWindowD0Ev[_ZN10MainWindowD0Ev]+0x7): undefined reference to `vtable for MainWindow'
test.o:test.cpp:(.text._ZN10MainWindowD0Ev[_ZN10MainWindowD0Ev]+0xf): more undefined references to `vtable for MainWindow' follow
collect2: error: ld returned 1 exit status
make: *** [tmp] Error 1

In general such errors are either because moc is not invoked or because of unimplemented virtual methods.

moc should be invoked automatically by qmake, and afaik QMainWindow doesn't have any pure virtual methods - so what is the problem here?

When I remove Q_OBJECT it works. Why is this? What is going on?

I see that Q_OBJECT tells moc to generate the signals/slots meta-data for that object, why can't it do that in this case?

Update:

Solution is to add #include "test.moc" just below class:

#include <QApplication>
#include <QMainWindow>

class MainWindow : public QMainWindow
{
    Q_OBJECT
};

#include "test.moc"  // <----------- HERE

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

    return a.exec();
}
Community
  • 1
  • 1
Andrew Tomazos
  • 66,139
  • 40
  • 186
  • 319
  • Once you throw Q_OBJECT into there, you have to 'moc' the file; moving the class declaration to a '.h' allows the generator to do all this underlying work. Otherwise, when you declare everything in the .cpp, you have to manually ('moc') the .cpp file and include the generated .cpp file somewhere in your source or dependancies. – dans3itz Jan 11 '13 at 14:38
  • @dans3itz: Is there a way to tell the pro file I want the cpp moced? I want to have the class definition in the cpp file. – Andrew Tomazos Jan 11 '13 at 14:47
  • @Andrew: of course you can put your def's where you want - but I would advise you to put them in a separate .h file and use Qt without modification. Separating the iplementation of the class from its definition is good practice, and you should have very good reasons not to do so. – Zane Jan 11 '13 at 14:55
  • 1
    @Zane: The very good reason is that this is throwaway code that I want to quickly write in a couple of minutes (prefer less), run it once, and then throw it away. In this circumstance "good practice" is not relevant and I just want it all in one file for ease of setup. – Andrew Tomazos Jan 11 '13 at 15:06

1 Answers1

10

It is because you declared the class inside the .cpp file. Put it into a separate .h header.

By default, the MOC is not invoked for source files, just for headers (edit: according to @Kamil, MOC is ran against .cpp source files, except that the generated .moc files should be #include-d manually in the .cpp files -- see my edit below).

Then, add the respective header file to the HEADERS variable inside the .pro file.

Of course, #include the same header into test.cpp.

Also, see this answer here:

https://stackoverflow.com/a/5854884/1284631

edit:

According to this thread: http://www.qtcentre.org/threads/28580-Why-does-qmake-moc-only-process-header-files

to force MOC running for .cpp files, you should add:

#include "test.moc"

right below the definition of your class. And re-run qmake. However, I did not test this.

edit2: See this reference for a discussion on the line on what OP is looking for:

http://harmattan-dev.nokia.com/docs/library/html/qt4/moc.html

Community
  • 1
  • 1
user1284631
  • 4,446
  • 36
  • 61
  • Is there a way to tell the pro file I want the cpp moced without moving it into a separate header? I intentionally want to use a single cpp. – Andrew Tomazos Jan 11 '13 at 14:46
  • Try to add it to the HEADERS variable: HEADERS += test.cpp. I think that you would also need to add: #include "moc_test.cpp" at the end of your test.cpp file (moc_ files are the files generated by the MOC). However, this solution is cumbersome. – user1284631 Jan 11 '13 at 14:49
  • WRONG: by default MOC is called even for .cpp files but you have to include filename.moc file within .cpp file – Kamil Klimek Jan 11 '13 at 14:52
  • @KamilKlimek: thanks, that just gives a new light to my latest edit. – user1284631 Jan 11 '13 at 14:55