Qt 的元对象系统(Meta-Object System)提供了对象之间通信的信号与槽机制、运行时类型信息和动态属性系统。
元对象系统由以下三个基础组成:
QObject
类是所有使用元对象系统的类的基类。- 在一个类的 private 部分声明
Q_OBJECT
宏,使得类可以使用元对象的特性,如动态属性、信号与槽。 - MOC(元对象编译器)为每个 QObject 的子类提供必要的代码来实现元对象系统的特性。
1 运行时类型信息
除了信号与槽机制外,元对象还提供如下一些功能:
QObject::metaObject()
函数返回类关联的元对象,元对象类 QMetaObject 包含了访问元对象的一些接口函数,例如 QMetaObject::className() 函数可在运行时返回类的名称字符串。QObject *obj = new QPushButton;
obj->metaObject()->className (); //返回"QPushButton"
QMetaObject::newInstance()
函数创建类的一个新的实例。QObject::inherits(const char *className)
函数判断一个对象实例是否是名称为 className 的类或 QObject 的子类的实例。例如:QTimer *timer = new QTimer; // QTimer 是 QObject 的子类
timer->inherits ("QTimer"); // 返回 true
timer->inherits ("QObject"); // 返回 true
timer->inherits ("QAbstractButton");//返回 false,不是 QAbstractButton 的子类
QObject::tr()
和QObject::trUtf8()
函数可翻译字符串,用于多语言界面设计,后续章会专门介绍多语言界面设计。QObject::setProperty()
和QObject::property()
函数用于通过属性名称动态设置和获取属性值2 动态转换
对于 QObject 及其子类,还可以使用qobject_cast()
函数进行动态投射(dynamic cast)。
例如,假设 QMyWidget 是 QWidget 的子类并且在类定义中声明了 Q_OBJECT 宏。创建实例使用下面的语句:QObject *obj = new QMyWidget;
- 变量 obj 定义为 QObject 指针,但它实际指向 QMyWidget 类,所以可以正确投射为 QWidget,即:
QWidget *widget = qobject_cast<QWidget *>(obj);
。从 QObject 到 QWidget 的投射是成功的,因为 obj 实际是 QMyWidget 类,是 QWidget 的子类。 - 也可以将其成功投射为 QMyWidget,即:
QMyWidget *myWidget = qobject_cast<QMyWidget *>(obj);
。投射为 QMyWidget 是成功的,因为 qobject_cast() 并不区分 Qt 内建的类型和用户自定义类型。 - 但是,若要将 obj 投射为 QLabel 则是失败的,即:
QLabel * label - qobject_cast<QLabel *>(obj);
。这样投射是失败的,返回指针 label 为 NULL,因为 QMyWidget 不是 QLabel 的子类。