您的位置:首页 > 移动开发 > Objective-C

QT的Meta-Object系统

2016-02-12 17:12 561 查看
原文:http://doc.qt.io/qt-5/metaobjects.html

Qt的meta-object system为对象间通信提供了signals和slots机制, 运行时类型检查(RTTI),和动态属性系统(dynamic property system)。

meta-object系统基于3件事情:

QObject为利用meta-object系统的对象提供了一个基类;
在类声明的私有段的Q_OBJECT宏被用来enable meta-object系统,比如dynamic property,signals和slots;
moc(Meta-Object Compiler)为每个QObject的子类提供必要的代码以实现meta-object的功能。

moc工具读取C++的源文件。若它发现有一个或多个类的声明含有Q_OBJECT宏,它就为每个类产生一个包含了meta-object代码的C++源文件。这个生成的源文件或者被包含在这个类的源文件中,或者更常见的是,被编译和与该类的实现进行链接。

除了为对象间通信提供signals和slots机制外(引入meta-object系统的主要原因),meta-object代码还提供如下的功能:

QObject::metaObject() 返回和该类相关的meta-object.
QMetaObject::className() 可以在运行时以string的形式返回类名,而不需要编译器的运行时类型检查(RTTI)的支持。
QObject::inherits() 返回一个对象是否是一个类的实例,该类继承了QObject继承树种的某个类。
QObject::tr()和QObject::trUtf8() 为国际化而翻译字符串。
QObject::setProperty()和QObject::property() 通过名称动态地set和get属性;
QMetaObejct::newInstance() 构造该类的一个新的实例

在QObject的一系列类上使用qobject_cast()可以做到动态类型转换。qobject_cast()函数和标准C++的dynamic_cast()类似,不需要RTTI的支持,就能在不同的动态库之间工作。它试图将它的参数转换成在尖括号中指定的指针类型。如果转换成功,就返回非0指针;否则返回0.

比如,假设MyWidget继承了QWidget,并且Q_OBJECT宏已经被声明:

QObject *obj = new MyWidget;
QWidget *widget = qobject_cast<QWidget *>(obj);  // correct
MyWidget *myWidget = qobject_cast<MyWidget *>(obj);  // correct
QLabel *label = qobject_cast<QLabel *>(obj);  // label is 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宏和meta-object代码是可能的。如果Q_OBJECT宏没有被使用,signals和slots,以及这里描述的其他功能就没有办法用了。从meta-object系统的观点来看,一个没有meta-object代码的QObject子类的对象,和它最近的祖先在meta-object code上是一致的。也就是说,比如,QMetaObject::className()将不会返回你的类的真正的名字,而是返回它的祖先的类名。

因此,我们强烈建议所有QObject的子类,都应该使用Q_OBJECT宏,无论它们是否使用了

signals、slots和properties.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: