Система метаобъектов
Система метаобъектов Qt предоставляет механизм сигналов и слотов для межобъектного взаимодействия, информацию о типе во время выполнения и динамическую систему свойств.
Система метаобъектов основана на трёх вещах:
- Класс QObject предоставляет базовый класс для объектов, которые могут использовать систему метаобъектов.
- Макрос Q_OBJECT внутри раздела «private» объявления класса используется для включения функций метаобъектов, таких как динамические свойства, сигналы и слоты.
- Компилятор метаобъектов Meta-Object Compiler (
moc) предоставляет каждому подклассу QObject необходимый код для реализации функций метаобъектов.
Инструмент moc считывает файл исходного кода C++. Если он находит одно или несколько объявлений классов, которые содержат макрос Q_OBJECT, он генерирует другой файл исходного кода C++, который содержит код метаобъектов для каждого из этих классов. Этот сгенерированный файл исходного кода либо #include в файл исходного кода класса, или, чаще, компилируется и подключается к реализации класса.
Помимо предоставления механизма сигналов и слотов для связи между объектами (главная причина введения системы), код метаобъектов предоставляет следующие дополнительные функции:
- QObject::metaObject() возвращает ассоциированный метаобъект для класса.
- QMetaObject::className() возвращает имя класса в виде строки во время выполнения без необходимости поддержки информации о типе во время выполнения (RTTI) через компилятор C++.
- Функция QObject::inherits() возвращает значение, указывающее, является ли объект экземпляром класса, унаследованного от указанного класса в иерархии наследования QObject.
- QObject::tr() переводит строки для международной локализации.
- QObject::setProperty() и QObject::property() динамически устанавливают и получают свойства по имени.
- QMetaObject::newInstance() создаёт новый экземпляр класса.
Также возможно выполнять динамические преобразования с использованием qobject_cast() для классов QObject. Функция qobject_cast() работает аналогично стандартному C++ dynamic_cast(), с преимуществами, что она не требует поддержки RTTI и работает через границы динамических библиотек. Она пытается преобразовать свой аргумент в указанный тип, возвращая ненулевой указатель, если объект имеет правильный тип (определённый во время выполнения), или nullptr, если тип объекта несовместим.
Например, предположим, что MyWidget наследуется от QWidget и объявлен с помощью макроса Q_OBJECT:
QObject *obj = new MyWidget;
Переменная obj, типа QObject *, фактически ссылается на объект MyWidget, поэтому мы можем преобразовать её должным образом:
QWidget *widget = qobject_cast<QWidget *>(obj);
Преобразование из QObject в QWidget выполняется успешно, потому что объект фактически является MyWidget, который является подклассом QWidget. Поскольку мы знаем, что obj является MyWidget, мы также можем преобразовать его в MyWidget *:
MyWidget *myWidget = qobject_cast<MyWidget *>(obj);
Преобразование в MyWidget выполняется успешно, потому что qobject_cast() не различает встроенные типы Qt и пользовательские типы.
QLabel *label = qobject_cast<QLabel *>(obj);
// label is 0 Преобразование в QLabel, с другой стороны, не выполняется. Указатель затем устанавливается в 0. Это позволяет обращаться с объектами разных типов по-разному во время выполнения, в зависимости от типа:
if (QLabel *label = qobject_cast<QLabel *>(obj)) {
label->setText(tr("Ping"));
} else if (QPushButton *button = qobject_cast<QPushButton *>(obj)) {
button->setText(tr("Pong!"));
} Хотя использование QObject в качестве базового класса без макроса Q_OBJECT и без кода метаобъектов возможно, ни сигналы и слоты, ни другие описанные здесь функции не будут доступны, если макрос Q_OBJECT не используется. С точки зрения системы метаобъектов, подкласс QObject без метакода эквивалентен его ближайшему предку с кодом метаобъектов. Это означает, что, например, QMetaObject::className() не вернёт фактическое имя вашего класса, а имя класса этого предка.
Поэтому мы настоятельно рекомендуем всем подклассам QObject использовать макрос Q_OBJECT, независимо от того, используют ли они на самом деле сигналы, слоты и свойства.
См. также QMetaObject, Систему свойств Qt и Сигналы и слоты.
© The Qt Company Ltd
Licensed under the GNU Free Documentation License, Version 1.3.
https://doc.qt.io/qt-6.2/metaobjects.html