Использование мета-объектного компилятора (Meta-Object Compiler, moc)
|
Опция | Описание |
---|---|
-o<file> | Записывает вывод в файл <file> вместо записи в стандартный вывод. |
-f[<file>] | Задает генерацию оператора #include в вывод. Установлено по умолчанию для заголовочных файлов, расширения которых начинаются с H или h. Эта опция полезна, если у вас есть заголовочные файлы, в которых не соблюдаются стандартные соглашения именования. Часть <file> является необязательной. |
-i | Не генерировать оператор #include в выводе. Её можно использовать для запуска moc с файлом C++, содержащим одно или более объявлений класса. Вы можете затем использовать #include чтобы включить мета-объектный код в файл .cpp. |
-nw | Не генерировать никаких предупреждений. (Не рекомендуется.) |
-p<path> | Заставляет moc добавлять <path>/ в начало имени файла в сгенерированном операторе #include. |
-I<dir> | Добавляет каталог к пути поиска заголовочных файлов. |
-E | Только для предварительной обработки; не генерировать мета-объектный код. |
-D<macro>[=<def>] | Задает макрос с необязательным определением. |
-U<macro> | Отменяет определение макроса. |
@<file> | Читает дополнительные опции командной строки из файла <file>. Каждая строка файла трактуется как одна опция. Пустые строки игнорируются. Обратите внимание на то, что эта опция не поддерживается внутри самого файла опций (т.е. файл опций не может "включить" другой файл). |
-h | Выводит на экран использование и список опций. |
-v | Выводит на экран номер версии moc'а. |
-Fdir | Mac OS X. Добавляет каталог фреймворка dir в начало списка каталогов, в которых производится поиск заголовочных файлов. Эти каталоги чередуются с заданными с помощью опций -I и просматриваются по порядку слева направо (смотрите оперативную страницу руководства для gcc). Обычно используют -F /Library/Frameworks/ |
Вы можете явно указать moc не производить синтаксический разбор частей заголовочного файла. moc определяет идентификатор препроцессора Q_MOC_RUN. Любой код, окружённый конструкцией
#ifndef Q_MOC_RUN ... #endif
будет пропущен moc'ом.
moc предупредит вас о количестве опасных или недопустимых конструкций в объявлениях класса Q_OBJECT.
Если вы получили ошибки компоновки на завершающей фазе сборки вашей программы, скажем что YourClass::className() не определен или что в YourClass отсутствует vtable, то что-то сделано неправильно. Очень часто забывают скомпилировать или включить с помощью #include сгенерированный moc код C++, или (в первом случае) включить этот объектный файл в команду компоновки. Если вы используете qmake, попробуйте перезапустить его для обновления вашего make-файла. Будет сделано все, что нужно.
moc не обрабатывает весь C++. Главная проблема - что классы-шаблоны не могут содержать сигналов или слотов. Вот пример:
class SomeTemplate<int> : public QFrame { Q_OBJECT ... signals: void mySignal(int); };
Другое ограничение заключается в том, что moc не расширяет макросы, поэтому вы не можете, например, использовать макрос для объявления сигнала/слота или использовать его для объявления базового класса для QObject.
Менее значимо, что перечисленные конструкции являются недопустимыми. Все из них имеют альтернативы, которые, мы полагаем, в большинстве случаев являются более подходящими, поэтому удаление этих ограничений для нас не имеет высокого приоритета.
Если вы используете множественное наследование, то moc предполагает что первый класс, от которого идет наследование, является подклассом QObject. Также убедитесь, что только первый класс, от которого идет наследование, является QObject.
// правильно class SomeClass : public QObject, public OtherClass { ... };
Виртуальное наследование с помощью QObject не поддерживается.
В большинстве случаев, когда вы обдумываете использование указателей на функцию в качестве параметров сигналов или слотов, мы думаем что наследование является более подходящим вариантом. Вот пример недопустимого синтаксиса:
class SomeClass : public QObject { Q_OBJECT public slots: void apply(void (*apply)(List *, void *), char *); // НЕПРАВИЛЬНО };
Вы можете обойти это ограничение, например так:
typedef void (*ApplyFunction)(List *, void *); class SomeClass : public QObject { Q_OBJECT public slots: void apply(ApplyFunction, char *); };
Иногда будет даже лучше заменить указатель на функцию наследованием и виртуальными функциями.
Когда проверяются сигнатуры аргументов, QObject::connect() сравнивает типы данных посимвольно. Соответственно, Alignment и Qt::Alignment будут рассматриваться как два отдельных типа. Чтобы обойти это ограничение убедитесь, что полностью уточнили типы данных когда объявляли сигналы и слоты и когда создавали соединения. Например:
class MyClass : public QObject { Q_OBJECT enum Error { ConnectionRefused, RemoteHostClosed, UnknownError }; signals: void stateChanged(MyClass::Error error); };
Так как moc не расширяет директивы #define, тип макросов, который получает аргумент, не будет работать в сигналах и слотах. Вот некорректный пример:
#ifdef ultrix #define SIGNEDNESS(a) unsigned a #else #define SIGNEDNESS(a) a #endif class Whatever : public QObject { Q_OBJECT signals: void someSignal(SIGNEDNESS(int)); };
Макрос без параметров будет работать.
Вот пример проблемной конструкции:
class A { public: class B { Q_OBJECT public slots: // НЕПРАВИЛЬНО void b(); }; };
Сигналы и слоты могут возвращать типы, но возвращаемые ссылки на сигналы или на слоты будут трактоваться как возвращаемое пустое значение (void).
moc будет жаловаться, если вы попытаетесь поместить в разделы класса signals или slots вместо сигналов и слотов другие конструкции.
Смотрите также Мета-объектная система, Сигналы и слоты и Система свойств Qt.
Copyright © 2009 Nokia Corporation and/or its subsidiary(-ies) | Торговые марки | Qt 4.5.3 |
Попытка перевода Qt документации. Если есть желание присоединиться, или если есть замечания или пожелания, то заходите на форум: Перевод Qt документации на русский язык... Люди внесшие вклад в перевод: Команда переводчиков |