Что делает макрос Q_OBJECT? Зачем всем объектам Qt нужен этот макрос?
132
Я только начал использовать Qt и заметил, что во всех примерах определений классов макрос указан Q_OBJECTв первой строке. Какова цель этого макроса препроцессора?
Компилятор метаобъектов moc - это программа, которая обрабатывает расширения Qt C ++.
Инструмент moc читает файл заголовка C ++. Если он находит одно или несколько объявлений классов, содержащих макрос Q_OBJECT, он создает исходный файл C ++, содержащий мета-объектный код для этих классов. Среди прочего, метаобъектный код требуется для механизма сигналов и слотов, информации о типе времени выполнения и системы динамических свойств.
почему мне нужно не объяснительно писать, Q_OBJECT::connect()а просто connect()?
mLstudent33
19
Он просто сообщает предварительному компилятору, что этот класс имеет элементы графического интерфейса и его нужно запускать через 'moc', вам нужно только добавить это в классы, которые используют механизм сигнала / слота.
Но это будет незаметно игнорироваться в любых других классах - это просто увеличивает время сборки.
Также неверно, что он нужен только для классов, использующих механизм сигнал / слот. Отсутствие Q_OBJECTломки qobject_castи самоанализа. Это может привести к некоторому недоумению, так что это плохая идея.
Восстановите Монику
2
Неправда, что Q_OBJECT"незаметно" игнорируется в любых других (не QObject) классах. Согласно стандарту C ++, он вводит неопределенное поведение, объявляя несколько функций-членов и переменных, которые никогда не определяются. Он также загрязняет пространство имен вашего класса определенными QObjectчленами. Например, a Q_OBJECTможет сломать несвязанный класс, который содержит вызываемый метод metaObject.
Восстановить Монику
2
Это неверно. Хотя вы, вероятно, захотите оснастить Q_OBJECTмакросом большинство gui-классов , имеет смысл иметь не-gui-классы с макросом, а также gui-классы без макроса. Макрос полезен, но не ограничивается и не требуется для классов gui.
Pasbi 06
9
MOC (компилятор метаобъектов) преобразует файлы заголовков, включенные в макрос Q_OBJECT, в эквивалентный исходный код C ++. Он в основном управляет механизмом сигнального слота и делает его понятным для компилятора C ++.
Это неверно: Q_OBJECTмакрос раскрывается компилятором, moc для этого не нужен. Moc ничего не делает с самим макросом, но он генерирует определения переменных-членов и методов, объявленныхQ_OBJECT макросом .
Инструмент moc читает исходный файл C ++. Если он обнаруживает одно или несколько объявлений классов, содержащих макрос Q_OBJECT, он создает другой исходный файл C ++, который содержит код метаобъекта для каждого из этих классов. Этот сгенерированный исходный файл либо # включается в исходный файл класса, либо, как правило, компилируется и связывается с реализацией класса.
Макрос Q_OBJECT должен появляться в закрытом разделе определения класса, который объявляет свои собственные сигналы и слоты или использует другие сервисы, предоставляемые мета-объектной системой Qt.
Инструмент moc читает файл заголовка C ++. Если он находит одно или несколько объявлений классов, содержащих макрос Q_OBJECT, он создает исходный файл C ++, содержащий мета-объектный код для этих классов. Среди прочего, метаобъектный код требуется для механизма сигналов и слотов, информации о типе времени выполнения и системы динамических свойств.
Макрос Q_OBJECT расширяется препроцессором, чтобы объявить несколько функций-членов, которые реализованы moc; если вы получаете ошибки компилятора в строках «неопределенная ссылка на vtable для LcdNumber», вы, вероятно, забыли запустить moc или включить вывод moc в команду ссылки.
В gcc -Eвы можете увидеть расширенные макросы. Это то, что Q_OBJECTрасширяется в gcc в Linux. Имейте в виду, что это может зависеть от платформы и может меняться в зависимости от версии QT. Как видите, это не просто тег для компилятора moc.
Макрос Q_OBJECT должен появляться в закрытом разделе определения класса, который объявляет свои собственные сигналы и слоты или использует другие сервисы, предоставляемые мета-объектной системой Qt.
Это вводит в заблуждение: Q_OBJECTмакрос должен присутствовать в каждом производном классе QObject. Ваш код будет слегка нарушен, когда макрос отсутствует, и то, что он скомпилирован, не делает его нормальным.
Восстановить Монику
@KubaOber у вас есть пример кода, который компилируется, но не работает, когда Q_OBJECTмакрос отсутствует?
Крис
2
Если вы посмотрите на реализацию Q_OBJECT, вы обнаружите, что в ней используются спецификаторы доступа. Так ли макрос должен появиться в под private, protectedили publicспецификаторы не имеет никакого отношения - это просто условность , чтобы поместить его в голове класса.
Ответы:
Из документации Qt :
источник
Q_OBJECT::connect()
а простоconnect()
?Он просто сообщает предварительному компилятору, что этот класс имеет элементы графического интерфейса и его нужно запускать через 'moc', вам нужно только добавить это в классы, которые используют механизм сигнала / слота.
Но это будет незаметно игнорироваться в любых других классах - это просто увеличивает время сборки.
источник
Q_OBJECT
ломкиqobject_cast
и самоанализа. Это может привести к некоторому недоумению, так что это плохая идея.Q_OBJECT
"незаметно" игнорируется в любых других (неQObject
) классах. Согласно стандарту C ++, он вводит неопределенное поведение, объявляя несколько функций-членов и переменных, которые никогда не определяются. Он также загрязняет пространство имен вашего класса определеннымиQObject
членами. Например, aQ_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.источник
Макрос Q_OBJECT должен появляться в закрытом разделе определения класса, который объявляет свои собственные сигналы и слоты или использует другие сервисы, предоставляемые мета-объектной системой Qt.
источник
Q_OBJECT
макрос должен присутствовать в каждом производном классеQObject
. Ваш код будет слегка нарушен, когда макрос отсутствует, и то, что он скомпилирован, не делает его нормальным.Q_OBJECT
макрос отсутствует?Q_OBJECT
, вы обнаружите, что в ней используются спецификаторы доступа. Так ли макрос должен появиться в подprivate
,protected
илиpublic
спецификаторы не имеет никакого отношения - это просто условность , чтобы поместить его в голове класса.