元对象系统(The Meta-Object System)


Qt的元对象系统(meta-object system)提供信号与槽机制,可用于对象间通信、运行时类别信息(RTTI)和动态属性系统。

 

元对象系统基于三个方面:

QObject:以它作为基类的对象才能实现元对象系统的特性。

Q_OBJECT: 在类的私有区声明这个宏可以打开诸如动态属性、信号与槽等元对象功能。

Meta-Object 编译器 (moc给每个QObject 的子类生成用以实现各种元对象功能的代码。

moc工具会扫描C++源文件,如果发现有包含Q_OBJECT宏的类声明,就生成另外一个包含这些类的元对象代码的C++源文件。生成的源文件要么在类源文件里用#include包含,或者(更常见)与类的实现代码直接进行编译连接。
    
除了提供信号与槽的对象间通讯机制(引入元对象系统的主要原因),元对象还提供以下功能:

QObject::metaObject() 返回类所属的meta-object(元对象)

QMetaObject::className() 在运行时以字符串形式返回类名,无需C++编译器提供运行时类别信息(RTTI)的支持。

QObject::inherits() 函数检查一个对象是否是QObject继承树内一个子类的实例。

QObject::tr() and QObject::trUtf8() 国际化而翻译字符串。

QObject::setProperty() 和 QObject::property() 以名字方式动态地设置属性。

QMetaObject::newInstance() 构造类的新实例。

qobject_cast()方法也可以对QObject的派生类对象进行动态类型转换。qobject_cast()方法跟标准C++dynamic_cast()很像,但它不需要RTTI支持并且可以跨动态链接库转换。这个方法会尝试把参数转换成尖括号内的类型,如果对象有正确的类型(在运行时检查)它就返回一个非零的指针,如果对象类型不兼容时则返回0
例如,假设MyWidget 是继承自QWidget 并且声明了宏Q_OBJECT

     QObject *obj = new MyWidget;

这个 obj变量的类型是QObject *,实际上指向一个MyWidget对象,所以我们可以正常的把它做类型转换:

     QWidget *widget = qobject_cast<QWidget *>(obj);

因为这个obj对象实际上就是MyWidgetMyWidgetQwidget的子类,因此从QObject 到 QWidget的类型转换是成功的。 既然我们知道objMyWidget类型的,我们也可以把它转换成 MyWidget *

     MyWidget *myWidget = qobject_cast<MyWidget *>(obj);

转换到MyWidget类型也是成功的,因为 qobject_cast() 并不区分内建的Qt类型和自定义类型。

     QLabel *label = qobject_cast<QLabel *>(obj);

     // 此时label 是 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 宏(即不用任何元对象代码),但是信号与槽以及上面所说的其他功能就就都不能用了。从元对象系统的角度来看,一个不用元对象代码的QObject 子类是跟它们使用元对象代码的祖先类是等价的。比方说QMetaObject::className() 就不会返回你的类的名字,而是返回使用元对象代码的最近祖先类(ancestor class)的名字。
因此我们强烈建议不管用不用信号与槽和属性,所有QObject的派生类都应该使用Q_OBJECT宏。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值