Я только начал использовать Qt и заметил, что во всех примерах определений классов макрос указан Q_OBJECT
в первой строке. Какова цель этого макроса препроцессора?
Я только начал использовать Qt и заметил, что во всех примерах определений классов макрос указан Q_OBJECT
в первой строке. Какова цель этого макроса препроцессора?
Ответы:
Из документации Qt :
Компилятор метаобъектов moc - это программа, которая обрабатывает расширения Qt C ++.
Инструмент moc читает файл заголовка C ++. Если он находит одно или несколько объявлений классов, содержащих макрос Q_OBJECT, он создает исходный файл C ++, содержащий мета-объектный код для этих классов. Среди прочего, метаобъектный код требуется для механизма сигналов и слотов, информации о типе времени выполнения и системы динамических свойств.
Q_OBJECT::connect()
а просто connect()
?
Он просто сообщает предварительному компилятору, что этот класс имеет элементы графического интерфейса и его нужно запускать через 'moc', вам нужно только добавить это в классы, которые используют механизм сигнала / слота.
Но это будет незаметно игнорироваться в любых других классах - это просто увеличивает время сборки.
Q_OBJECT
ломки qobject_cast
и самоанализа. Это может привести к некоторому недоумению, так что это плохая идея.
Q_OBJECT
"незаметно" игнорируется в любых других (не QObject
) классах. Согласно стандарту C ++, он вводит неопределенное поведение, объявляя несколько функций-членов и переменных, которые никогда не определяются. Он также загрязняет пространство имен вашего класса определенными QObject
членами. Например, a Q_OBJECT
может сломать несвязанный класс, который содержит вызываемый метод metaObject
.
Q_OBJECT
макросом большинство gui-классов , имеет смысл иметь не-gui-классы с макросом, а также gui-классы без макроса. Макрос полезен, но не ограничивается и не требуется для классов gui.
MOC (компилятор метаобъектов) преобразует файлы заголовков, включенные в макрос Q_OBJECT, в эквивалентный исходный код C ++. Он в основном управляет механизмом сигнального слота и делает его понятным для компилятора C ++.
Q_OBJECT
макрос раскрывается компилятором, moc для этого не нужен. Moc ничего не делает с самим макросом, но он генерирует определения переменных-членов и методов, объявленныхQ_OBJECT
макросом .
1 Из документации Qt системы мета-объектов
Инструмент moc читает исходный файл C ++. Если он обнаруживает одно или несколько объявлений классов, содержащих макрос Q_OBJECT, он создает другой исходный файл C ++, который содержит код метаобъекта для каждого из этих классов. Этот сгенерированный исходный файл либо # включается в исходный файл класса, либо, как правило, компилируется и связывается с реализацией класса.
2 Из Qt документации THE Q_OBJECT
Макрос Q_OBJECT должен появляться в закрытом разделе определения класса, который объявляет свои собственные сигналы и слоты или использует другие сервисы, предоставляемые мета-объектной системой Qt.
3 Из Qt документации moc
Инструмент moc читает файл заголовка C ++. Если он находит одно или несколько объявлений классов, содержащих макрос Q_OBJECT, он создает исходный файл C ++, содержащий мета-объектный код для этих классов. Среди прочего, метаобъектный код требуется для механизма сигналов и слотов, информации о типе времени выполнения и системы динамических свойств.
4 Из документации Qt по сигналам и слотам
Макрос Q_OBJECT расширяется препроцессором, чтобы объявить несколько функций-членов, которые реализованы moc; если вы получаете ошибки компилятора в строках «неопределенная ссылка на vtable для LcdNumber», вы, вероятно, забыли запустить moc или включить вывод moc в команду ссылки.
В gcc -E
вы можете увидеть расширенные макросы. Это то, что Q_OBJECT
расширяется в gcc в Linux. Имейте в виду, что это может зависеть от платформы и может меняться в зависимости от версии QT. Как видите, это не просто тег для компилятора moc.
# 11 "mainwindow.hh"
#pragma GCC diagnostic push
# 11 "mainwindow.hh"
# 11 "mainwindow.hh"
#pragma GCC diagnostic ignored "-Wsuggest-override"
# 11 "mainwindow.hh"
static const QMetaObject staticMetaObject; virtual const QMetaObject *metaObject() const; virtual void *qt_metacast(const char *); virtual int qt_metacall(QMetaObject::Call, int, void **); static inline QString tr(const char *s, cons
t char *c = nullptr, int n = -1) { return staticMetaObject.tr(s, c, n); } __attribute__ ((__deprecated__)) static inline QString trUtf8(const char *s, const char *c = nullptr, int n = -1) { return staticMetaObject.tr(s, c, n); } private:
# 11 "mainwindow.hh"
#pragma GCC diagnostic ignored "-Wattributes"
# 11 "mainwindow.hh"
__attribute__((visibility("hidden"))) static void qt_static_metacall(QObject *, QMetaObject::Call, int, void **);
# 11 "mainwindow.hh"
#pragma GCC diagnostic pop
# 11 "mainwindow.hh"
struct QPrivateSignal {};
Макрос Q_OBJECT должен появляться в закрытом разделе определения класса, который объявляет свои собственные сигналы и слоты или использует другие сервисы, предоставляемые мета-объектной системой Qt.
Q_OBJECT
макрос должен присутствовать в каждом производном классе QObject
. Ваш код будет слегка нарушен, когда макрос отсутствует, и то, что он скомпилирован, не делает его нормальным.
Q_OBJECT
макрос отсутствует?
Q_OBJECT
, вы обнаружите, что в ней используются спецификаторы доступа. Так ли макрос должен появиться в под private
, protected
или public
спецификаторы не имеет никакого отношения - это просто условность , чтобы поместить его в голове класса.