3.4. Meta Object Compiler (moc)

The Meta Object Compiler (moc) is a useful addition to Qt. It is a tool that saves a lot of work, and it is very simple to use.

It converts Qt class definitions into C++ code.

3.4.1. Using the moc Tool

You probably already know that a compiler converts code into ones and zeros. The code may sometimes be understandable, but the ones and zeros are not.

The moc is not a compiler, although the name may suggest that. The moc looks in your code and searches for certain keywords. When a keyword is found, it is replaced by other code. This saves you a lot of programming because the resulting code is much more complex than the original. The moc Keywords

The moc keywords are Q_OBJECT, public slots:, protected slots:, private slots:, and signals:.

The Q_OBJECT keyword tells moc that the class is a Qt class.

All slots must be defined below a slots keyword. Slots can be public, protected, or private. You must specify the access mode before the slots keyword (all public slots are defined below public slots for example).

All signals must be defined below the signals: keyword. Signals are always public.

3.4.2. Sample Use of the moc

You will now see how to use moc with a small sample program. The main window in the program contains a button. When you click the button, the slot slotButton() is executed. Listing 3.6 contains the code:

Example 3.6. mywindow.h: Class Declaration with moc Keywords

   2   1: #include <qwidget.h>
   3  2: #include <qpushbutton.h>
   4  3: 
   5  4: class MyWindow : public QWidget
   6  5: {
   7  6:   Q_OBJECT
   8  7: public:
   9  8:   MyWindow();
  10  9: public slots:
  11 10:   void slotButton();
  12 11: private:
  13 12:   QPushButton *button;
  14 13: };

Listing 3.7 shows the class implementation. You must put the class definition and class implementation in different files, because the class implementation needs the code that moc generates.

Example 3.7. mywindow.cpp: Class Implementation for MyWindow

   2  1: #include "mywindow.moc"
   3  2: #include <iostream.h>
   4  3: 
   5  4: MyWindow::MyWindow() : QWidget()
   6  5: {
   7  6:   button = new QPushButton("Click me", this);
   8  7:   button->setGeometry(10,10,100,40);
   9  8:   button->show();
  10  9: 
  11 10:   connect(button, SIGNAL(clicked()), this, SLOT(slotButton()));
  12 11: }
  13 12: 
  14 13: void slotButton()
  15 14: {
  16 15:   cout << "You clicked me" << endl;
  17 16: }

Listing 3.8 shows what the main program file looks like. It uses the MyWindow class which you have just created.

Example 3.8. main.cpp: The Main Program File

   2  1: #include <kapp.h>
   3  2: #include "mywindow.h"
   4  3: 
   5  4: int main(int argc, char **argv)
   6  5: {
   7  6:   KApplication app(argc, argv);
   8  7:   MyWindow window;
   9  8:   window.setGeometry(100,100,200,100);
  10  9:   window.setCaption("Aha!");
  11 10:   app.setMainWidget(&window);
  12 11:   window.show();
  13 12:   return app.exec();
  14 13: }

Now you will compile the program. Common C++ programs are compiled in two steps. First, all object files are created, and then the object files are linked into a program.

Creating all object files takes two steps when you are using signals and slots, because you must use moc first to precompile the class definitions.

Note that the main.cpp file in Listing 3.8 can be compiled into an object file directly. No moc keywords are in it, nor does it include any files generated by moc. To create the object file for main.cpp, type the following:

   2 g++ -I$QTDIR/include -c main.cpp

The mywindow.cpp file, containing the class declaration for MyWindow, can't be compiled yet. The class declaration contains some moc keywords (Q_OBJECT, public slots), which must be translated into C++ code first. To translate, use the moc tool. The following command precompiles the mywindow.h file and the result is written to mywindow.moc:

   2 moc mywindow.h -o mywindow.moc

Now you can compile the mywindow.cpp file like so:

   2 g++ -I/$QTDIR/include -c mywindow.cpp

At this point, all object files have been created.

To link the object files into an executable program, use the following command:

   2 g++ -o myprog main.o mywindow.o -L/$QTDIR/lib -lqt

The name of the executable file will be myprog.

Now you can execute your program.

I'll now give you a quick summary of the compiling process. The first step is to precompile all necessary files with moc. All class definitions that contains moc keywords must be precompiled. The second step is to create all the object files. The third and last step is to link all the object files together.