What moc Actually Generates
I added a signal to a small Qt 3 class today, rebuilt, and received an undefined reference to the class’s virtual table. That message sounds like a C++ problem. In this case it meant I had forgotten about moc.
Qt’s signals and slots need information that the C++ compiler does not produce. A class using them declares Q_OBJECT:
class Counter : public QObject
{
Q_OBJECT
public:
Counter(QObject *parent = 0, const char *name = 0);
signals:
void changed(int value);
public slots:
void setValue(int value);
};
The Meta Object Compiler reads that declaration and writes ordinary C++ containing the meta-object table and dispatch code. The generated file supplies, among other things, the pieces behind className(), signal activation, and calls made through the string-based connect() mechanism.
In a KDE autotools project the build rules normally run moc for headers containing Q_OBJECT. If I put the class declaration in a .cpp file, I include its generated output at the bottom:
#include "counter.moc"
After adding or removing Q_OBJECT, regenerating the build files is sometimes necessary. A clean rebuild is also cheaper than interpreting every vtable error as an omen.
I like signals and slots because the sender does not need to know the receiver. The caveat is that the compiler cannot check the old SIGNAL() and SLOT() strings fully. A connection can compile and then complain at run time, so I watch the diagnostic output and keep signatures simple.