元对象系统
Qt 的元对象系统为对象间通信、运行时类型信息和动态属性系统提供了信号和插槽机制。
元对象系统基于以下三个方面:
- QObject 类为可以利用元对象系统的对象提供了一个基类。
- Q_OBJECT 宏用于启用元对象功能,如动态属性、信号和槽。
- 宏 Meta-Object Compiler(
moc
) 为每个QObject 子类提供实现元对象功能所需的代码。
moc
工具读取 C++ 源文件。如果发现一个或多个类的声明包含Q_OBJECT 宏,它就会生成另一个 C++ 源文件,其中包含每个类的元对象代码。生成的源文件可以#include
'd到类的源文件中,或者更常见的是与类的实现进行编译和链接。
除了为对象之间的通信提供信号和插槽机制(引入该系统的主要原因)外,元对象代码还提供以下附加功能:
- QObject::metaObject() 返回类的相关meta-object 。
- QMetaObject::className() 在运行时以字符串形式返回类名,无需 C++ 编译器提供本地运行时类型信息(RTTI)支持。
- 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
对象,因此我们可以对其进行适当的转换:
从QObject 向QWidget 的转换是成功的,因为该对象实际上是MyWidget
,而 是QWidget 的子类。由于我们知道obj
是MyWidget
,所以我们也可以将其转换为MyWidget *
:
MyWidget *myWidget = qobject_cast<MyWidget *>(obj);
从MyWidget
转换到qobject_cast 是成功的,因为 () 并不区分内置 Qt XML 类型和自定义类型。
另一方面,向QLabel 的转换失败。这样,在运行时就可以根据类型对不同类型的对象进行不同处理:
if (QLabel *label = qobject_cast<QLabel *>(obj)) { label->setText(tr("Ping")); } else if (QPushButton *button = qobject_cast<QPushButton *>(obj)) { button->setText(tr("Pong!")); }
虽然在不使用Q_OBJECT 宏和不使用元对象代码的情况下,也可以将QObject 用作基类,但如果不使用Q_OBJECT 宏,则信号和槽以及此处描述的其他功能都无法使用。从元对象系统的角度来看,没有元代码的QObject 子类等同于有元对象代码的最接近的祖先。例如,这意味着QMetaObject::className() 将不会返回您的类的实际名称,而是返回该祖先的类名。
另请参阅 QMetaObject 、Qt 的属性系统以及信号和插槽。
© 2025 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.