This question already has an answer here:
This is my header:
#ifndef BARELYSOCKET_H
#define BARELYSOCKET_H
#include <QObject>
//! The First Draw of the BarelySocket!
class BarelySocket: public QObject
{
Q_OBJECT
public:
BarelySocket();
public slots:
void sendMessage(Message aMessage);
signals:
void reciveMessage(Message aMessage);
private:
// QVector<Message> reciveMessages;
};
#endif // BARELYSOCKET_H
This is my class:
#include <QTGui>
#include <QObject>
#include "type.h"
#include "client.h"
#include "server.h"
#include "barelysocket.h"
BarelySocket::BarelySocket()
{
//this->reciveMessages.clear();
qDebug("BarelySocket::BarelySocket()");
}
void BarelySocket::sendMessage(Message aMessage)
{
}
void BarelySocket::reciveMessage(Message aMessage)
{
}
I get a Linker error:
undefined reference to 'vtable for BarelySocket'
- This implies that I have a virtual method not implemented. But there are no virtual methods in my class.
- I commented out the vector thinking that it was the cause, but the error did not go away.
- The
Message
is a complexstruct
, but even usingint
instead did not fix things.
When you derive a class from QOBject (and use the Q_OBJECT macro), don't forget to specifically define and create both the constructor and destructor classes. It's not enough to use the compiler default constructor/destructors. The advice on cleaning/running qmake (and clearing out your moc_ files) still applies. This fixed my similar problem.
I ran into this error after I created a little class inside a small "main.cpp" file that I had created to test something.
After futzing for an hour or so, I finally moved that class out of main.cpp and into a standalone hpp file, updated the .pro (project) file and the project then built perfectly fine. That may not have been the issue here but I figured it would be useful information anyway.
I've seen a lot of ways to solve the problem, but no explanation for why it happens, so here goes.
When the compiler sees a class with virtual functions (directly declared or inherited), it must generate a vtable for that class. Since classes are generally defined in headers (and thus appear in multiple translation units), the question is where to place the vtable.
In general, the problem can be solved by generating the vtable in every TU where the class is defined, and then let the linker eliminate duplicates. Since class definitions are required to be the same on every occurrence by the ODR, this is safe. However, it also slows down compilation, bloats object files, and requires the linker to do more work.
As an optimization, therefore, compilers will, when possible, choose a specific TU to put the vtable in. In the common C++ ABI, this TU is the one where the key function of the class is implemented in, where the key function is the first virtual member function that is declared in the class, but not defined.
In the case of Qt classes, they usually start with the Q_OBJECT macro, and this macro contains the declaration
which, since it is the first virtual function in the macro, will generally be the first virtual function of the class and thus its key function. The compiler will therefore not emit the vtable in most TUs, only the one that implements
metaObject
. And this function's implementation is written automatically bymoc
when it processes the header. Thus, you need to havemoc
process your header to generate a new .cpp file, and then include the .cpp file in your compilation.So when you have a new header that defines a
QObject
-derived class, you need to rerunqmake
so that it updates your makefiles to runmoc
on the new header and compile the resulting .cpp file.I found another reason why you might see this - since
qmake
parses through your class files if you have modified them in a non-standard way you may get this error. In my case I had a custom dialog that inherited from QDialog, but I only wanted that to compile and run when building for Linux, not Windows or OSX. I just#ifdef __linux__
the class out so it didn't compile, but in Linux even though__linux__
was defined it was throwing offqmake
.Any time you add a new call to the Q_OBJECT macro, you need to run qmake again. The vtables issue you're referring to is directly related to that.
Just run qmake and you should be good to go assuming there are no other issues in your code.
From experience: oftentimes a qmake && make clean && make helps. I personally perceive that sometimes the change discovery / caching effects / whatever-I-don't-know xxxxx. I can't say why, but it's the first thing I do when I encounter this kind of error.
btw. there's a typo at > recive <
You forgot to call the QObject constructor in your constructor (in the initializer list). (It doesn't resolve the error though)