04-元对象系统
3.1.2 元对象系统
Qt的元对象系统(Meta-Object System)提供了对象之间通信的信号与槽机制、运行时类型信息和动态属性系统。
元对象系统由以下三个基础组成。
- QObject类是所有使用元对象系统的类的基类。
- 在一个类的private部分声明Q_OBJECT宏,使得类可以使用元对象的特性,如动态属性、信号与槽。
- MOC(元对象编译器)为每个QObject的子类提供必要的代码来实现元对象系统的特性。
构建项目时,MOC工具读取C++源文件,当它发现类的定义里有Q_OBJECT宏时,它就会为这个类生成另外一个包含有元对象支持代码的C++源文件,这个生成的源文件连同类的实现文件一起被编译和连接。
除了信号与槽机制外,元对象还提供如下一些功能。
- 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()函数可翻译字符串,用于多语言界面设计,在第16章会专门介绍多语言界面设计。
- QObject::setProperty()和QObject::property()函数用于通过属性名称动态设置和获取属性值。
对于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的子类。
使用动态投射,使得程序可以在运行时对不同的对象做不同的处理。