Мета-объектная система
Мета-объектная система основана на трёх вещах:
Инструмент moc читает файл исходных кодов C++. Если он находит один или более объявлений классов, содержащих макрос Q_OBJECT, он производит другой файл исходных кодов C++, который содержит мета-объектный код для каждого из этих классов. Полученный файл исходных кодов или подключается с помощью #include'а в исходном файле класса или, что применяется чаще, компилируется и линкуется вместе с реализацией класса. В дополнение к предоставляемому механизму сигналов и слотов для коммуникации между объектами (основной причине введения этой системы), мета-объектный код предоставляет следующие дополнительные возможности:
Кроме того, можно выполнить динамическое приведение типа используя qobject_cast() в классах QObject. Функция qobject_cast() ведёт себя аналогично стандартной функции C++ dynamic_cast(), с тем преимуществом, что она не требует поддержки RTTI и работает через границы динамических библиотек. Она пытается привести тип своего аргумента к указателю на тип, указанный в угловых скобках, возвращая ненулевой указатель если объект имеет корректный тип (определяется во время выполнения), или 0 если тип объекта является несовместимым incompatible. Например, предположим 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 и Сигналы и слоты.
|
Попытка перевода Qt документации. Если есть желание присоединиться, или если есть замечания или пожелания, то заходите на форум: Перевод Qt документации на русский язык... Люди внесшие вклад в перевод: Команда переводчиков |