Viadeo Twitter Google Bookmarks ! Facebook Digg del.icio.us MySpace Yahoo MyWeb Blinklist Netvouz Reddit Simpy StumbleUpon Bookmarks Windows Live Favorites 
Logo Documentation Qt ·  Page d'accueil  ·  Toutes les classes  ·  Classes principales  ·  Annotées  ·  Classes groupées  ·  Modules  ·  Fonctions  · 

Using the Meta-Object Compiler (moc)

The Meta-Object Compiler, moc, is the program that handles Qt's C++ extensions.

The moc tool reads a C++ header file. If it finds one or more class declarations that contain the Q_OBJECT macro, it produces a C++ source file containing the meta-object code for those classes. Among other things, meta-object code is required for the signals and slots mechanism, the run-time type information, and the dynamic property system.

The C++ source file generated by moc must be compiled and linked with the implementation of the class.

If you use qmake to create your makefiles, build rules will be included that call the moc when required, so you will not need to use the moc directly. For more background information on moc, see Why doesn't Qt use templates for signals and slots?

Usage

moc is typically used with an input file containing class declarations like this:

    class MyClass : public QObject
    {
        Q_OBJECT

    public:
        MyClass(QObject *parent = 0);
        ~MyClass();

    signals:
        void mySignal();

    public slots:
        void mySlot();
    };

In addition to the signals and slots shown above, moc also implements object properties as in the next example. The Q_PROPERTY() macro declares an object property, while Q_ENUMS() declares a list of enumeration types within the class to be usable inside the property system.

In the following example, we declare a property of the enumeration type Priority that is also called priority and has a get function priority() and a set function setPriority().

    class MyClass : public QObject
    {
        Q_OBJECT
        Q_PROPERTY(Priority priority READ priority WRITE setPriority)
        Q_ENUMS(Priority)

    public:
        enum Priority { High, Low, VeryHigh, VeryLow };

        MyClass(QObject *parent = 0);
        ~MyClass();

        void setPriority(Priority priority);
        Priority priority() const;
    };

The Q_FLAGS() macro declares enums that are to be used as flags, i.e. OR'd together. Another macro, Q_CLASSINFO(), allows you to attach additional name/value pairs to the class's meta-object:

    class MyClass : public QObject
    {
        Q_OBJECT
        Q_CLASSINFO("Author", "Oscar Peterson")
        Q_CLASSINFO("Status", "Active")

    public:
        MyClass(QObject *parent = 0);
        ~MyClass();
    };

The output produced by moc must be compiled and linked, just like the other C++ code in your program; otherwise, the build will fail in the final link phase. If you use qmake, this is done automatically. Whenever qmake is run, it parses the project's header files and generates make rules to invoke moc for those files that contain a Q_OBJECT macro.

If the class declaration is found in the file myclass.h, the moc output should be put in a file called moc_myclass.cpp. This file should then be compiled as usual, resulting in an object file, e.g., moc_myclass.obj on Windows. This object should then be included in the list of object files that are linked together in the final building phase of the program.

Writing Make Rules for Invoking moc

For anything but the simplest test programs, it is recommended that you automate running the moc. By adding some rules to your program's makefile, make can take care of running moc when necessary and handling the moc output.

We recommend using Trolltech's makefile generation tool, qmake, for building your makefiles. This tool generates a makefile that does all the necessary moc handling.

If you want to create your makefiles yourself, here are some tips on how to include moc handling.

For Q_OBJECT class declarations in header files, here is a useful makefile rule if you only use GNU make:

    moc_%.cpp: %.h
            moc $(DEFINES) $(INCPATH) $< -o $@

If you want to write portably, you can use individual rules of the following form:

    moc_foo.cpp: foo.h
            moc $(DEFINES) $(INCPATH) $< -o $@

You must also remember to add moc_foo.cpp to your SOURCES (substitute your favorite name) variable and moc_foo.o or moc_foo.obj to your OBJECTS variable.

Both examples assume that $(DEFINES) and $(INCPATH) expand to the define and include path options that are passed to the C++ compiler. These are required by moc to preprocess the source files.

While we prefer to name our C++ source files .cpp, you can use any other extension, such as .C, .cc, .CC, .cxx, and .c++, if you prefer.

For Q_OBJECT class declarations in implementation (.cpp) files, we suggest a makefile rule like this:

    foo.o: foo.moc

    foo.moc: foo.cpp
            moc $(DEFINES) $(INCPATH) -i $< -o $@

This guarantees that make will run the moc before it compiles foo.cpp. You can then put

    #include "foo.moc"

at the end of foo.cpp, where all the classes declared in that file are fully known.

Command-Line Options

Here are the command-line options supported by the moc:

OptionDescription
-o<file>Write output to <file> rather than to standard output.
-f[<file>]Force the generation of an #include statement in the output. This is the default for header files whose extension starts with H or h. This option is useful if you have header files that do not follow the standard naming conventions. The <file> part is optional.
-iDo not generate an #include statement in the output. This may be used to run the moc on on a C++ file containing one or more class declarations. You should then #include the meta-object code in the .cpp file.
-nwDo not generate any warnings. (Not recommended.)
-p<path>Makes the moc prepend <path>/ to the file name in the generated #include statement.
-I<dir>Add dir to the include path for header files.
-EPreprocess only; do not generate meta-object code.
-D<macro>[=<def>]Define macro, with optional definition.
-U<macro>Undefine macro.
-hDisplay the usage and the list of options.
-vDisplay moc's version number.

You can explicitly tell the moc not to parse parts of a header file. moc defines the preprocessor symbol Q_MOC_RUN. Any code surrounded by

    #ifndef Q_MOC_RUN
        ...
    #endif

is skipped by the moc.

Diagnostics

moc will warn you about a number of dangerous or illegal constructs in the Q_OBJECT class declarations.

If you get linkage errors in the final building phase of your program, saying that YourClass::className() is undefined or that YourClass lacks a vtable, something has been done wrong. Most often, you have forgotten to compile or #include the moc-generated C++ code, or (in the former case) include that object file in the link command. If you use qmake, try rerunning it to update your makefile. This should do the trick.

Limitations

moc does not handle all of C++. The main problem is that class templates cannot have signals or slots. Here is an example:

    class SomeTemplate<int> : public QFrame
    {
        Q_OBJECT
        ...

    signals:
        void mySignal(int);
    };

Another limitation is that moc does not expand macros, so you for example cannot use a macro to declare a signal/slot or use one to define a base class for a QObject.

Less importantly, the following constructs are illegal. All of them have alternatives which we think are usually better, so removing these limitations is not a high priority for us.

Multiple Inheritance Requires QObject to Be First

If you are using multiple inheritance, moc assumes that the first inherited class is a subclass of QObject. Also, be sure that only the first inherited class is a QObject.

    // correct
    class SomeClass : public QObject, public OtherClass
    {
        ...
    };

Virtual inheritance with QObject is not supported.

Function Pointers Cannot Be Signal or Slot Parameters

In most cases where you would consider using function pointers as signal or slot parameters, we think inheritance is a better alternative. Here is an example of illegal syntax:

    class SomeClass : public QObject
    {
        Q_OBJECT

    public slots:
        void apply(void (*apply)(List *, void *), char *); // WRONG
    };

You can work around this restriction like this:

    typedef void (*ApplyFunction)(List *, void *);

    class SomeClass : public QObject
    {
        Q_OBJECT

    public slots:
        void apply(ApplyFunction, char *);
    };

It may sometimes be even better to replace the function pointer with inheritance and virtual functions.

Enums and Typedefs Must Be Fully Qualified for Signal and Slot Parameters

When checking the signatures of its arguments, QObject::connect() compares the data types literally. Thus, Alignment and Qt::Alignment are treated as two distinct types. To work around this limitation, make sure to fully qualify the data types when declaring signals and slots, and when establishing connections. For example:

    class MyClass : public QObject
    {
        Q_OBJECT

        enum Error {
            ConnectionRefused,
            RemoteHostClosed,
            UnknownError
        };

    signals:
        void stateChanged(MyClass::Error error);
    };

Type Macros Cannot Be Used for Signal and Slot Parameters

Since moc doesn't expand #defines, type macros that take an argument will not work in signals and slots. Here is an illegal example:

    #ifdef ultrix
    #define SIGNEDNESS(a) unsigned a
    #else
    #define SIGNEDNESS(a) a
    #endif

    class Whatever : public QObject
    {
        Q_OBJECT

    signals:
        void someSignal(SIGNEDNESS(int));
    };

A macro without parameters will work.

Nested Classes Cannot Have Signals or Slots

Here's an example of the offending construct:

    class A
    {
    public:
        class B
        {
            Q_OBJECT

        public slots:   // WRONG
            void b();
        };
    };

Only Signals and Slots May Appear in the signals and slots Sections of a Class

moc will complain if you try to put other constructs in the signals or slots sections of a class than signals and slots.

See also Meta-Object System, Signals and Slots, and Qt's Property System.

Publicité

Best Of

Actualités les plus lues

Semaine
Mois
Année
  1. « Quelque chose ne va vraiment pas avec les développeurs "modernes" », un développeur à "l'ancienne" critique la multiplication des bibliothèques 103
  2. Pourquoi les programmeurs sont-ils moins payés que les gestionnaires de programmes ? Manquent-ils de pouvoir de négociation ? 56
  3. «Le projet de loi des droits du développeur» : quelles conditions doivent remplir les entreprises pour que le développeur puisse réussir ? 90
  4. Les développeurs détestent-ils les antivirus ? Un programmeur manifeste sa haine envers ces solutions de sécurité 31
  5. Qt Commercial : Digia organise un webinar gratuit le 27 mars sur la conception d'interfaces utilisateur et d'applications avec le framework 0
  6. Quelles nouveautés de C++11 Visual C++ doit-il rapidement intégrer ? Donnez-nous votre avis 10
  7. 2017 : un quinquennat pour une nouvelle version du C++ ? Possible, selon Herb Sutter 11
Page suivante
  1. Linus Torvalds : le "C++ est un langage horrible", en justifiant le choix du C pour le système de gestion de version Git 100
  2. Comment prendre en compte l'utilisateur dans vos applications ? Pour un développeur, « 90 % des utilisateurs sont des idiots » 231
  3. Quel est LE livre que tout développeur doit lire absolument ? Celui qui vous a le plus marqué et inspiré 96
  4. Apple cède et s'engage à payer des droits à Nokia, le conflit des brevets entre les deux firmes s'achève 158
  5. Nokia porte à nouveau plainte contre Apple pour violation de sept nouveaux brevets 158
  6. « Quelque chose ne va vraiment pas avec les développeurs "modernes" », un développeur à "l'ancienne" critique la multiplication des bibliothèques 103
  7. Quel est le code dont vous êtes le plus fier ? Pourquoi l'avez-vous écrit ? Et pourquoi vous a-t-il donné autant de satisfaction ? 83
Page suivante

Le Qt Developer Network au hasard

Logo

Comment fermer une application

Le Qt Developer Network est un réseau de développeurs Qt anglophone, où ils peuvent partager leur expérience sur le framework. Lire l'article.

Communauté

Ressources

Liens utiles

Contact

  • Vous souhaitez rejoindre la rédaction ou proposer un tutoriel, une traduction, une question... ? Postez dans le forum Contribuez ou contactez-nous par MP ou par email (voir en bas de page).

Qt dans le magazine

Cette page est une traduction d'une page de la documentation de Qt, écrite par Nokia Corporation and/or its subsidiary(-ies). Les éventuels problèmes résultant d'une mauvaise traduction ne sont pas imputables à Nokia. Qt 4.1
Copyright © 2012 Developpez LLC. Tous droits réservés Developpez LLC. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents et images sans l'autorisation expresse de Developpez LLC. Sinon, vous encourez selon la loi jusqu'à 3 ans de prison et jusqu'à 300 000 E de dommages et intérêts. Cette page est déposée à la SACD.
Vous avez déniché une erreur ? Un bug ? Une redirection cassée ? Ou tout autre problème, quel qu'il soit ? Ou bien vous désirez participer à ce projet de traduction ? N'hésitez pas à nous contacter ou par MP !
 
 
 
 
Partenaires

Hébergement Web