Qt 的元对象系统(Meta-Object System)提供了对象之间通信的信号与槽机制、运行时类型信息和动态属性系统。
元对象系统由以下三个基础组成:

  1. QObject类是所有使用元对象系统的类的基类。
  2. 在一个类的 private 部分声明 Q_OBJECT宏,使得类可以使用元对象的特性,如动态属性、信号与槽。
  3. MOC(元对象编译器)为每个 QObject 的子类提供必要的代码来实现元对象系统的特性。

    1 运行时类型信息

    除了信号与槽机制外,元对象还提供如下一些功能:
  • QObject::metaObject()函数返回类关联的元对象,元对象类 QMetaObject 包含了访问元对象的一些接口函数,例如 QMetaObject::className() 函数可在运行时返回类的名称字符串。

    1. QObject *obj = new QPushButton;
    2. obj->metaObject()->className (); //返回"QPushButton"
  • QMetaObject::newInstance() 函数创建类的一个新的实例。

  • QObject::inherits(const char *className)函数判断一个对象实例是否是名称为 className 的类或 QObject 的子类的实例。例如:

    1. QTimer *timer = new QTimer; // QTimer 是 QObject 的子类
    2. timer->inherits ("QTimer"); // 返回 true
    3. timer->inherits ("QObject"); // 返回 true
    4. 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 的子类