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作为基类而不使用Q_OBJECT宏和meta-object代码是可能的。如果Q_OBJECT宏没有被使用,signals和slots,以及这里描述的其他功能就没有办法用了。从meta-object系统的观点来看,一个没有meta-object代码的QObject子类的对象,和它最近的祖先在meta-object code上是一致的。也就是说,比如,QMetaObject::className()将不会返回你的类的真正的名字,而是返回它的祖先的类名。
因此,我们强烈建议所有QObject的子类,都应该使用Q_OBJECT宏,无论它们是否使用了
signals、slots和properties.
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.
相关文章推荐
- Objective-C的知识小拓展
- Objective-C 和 C的对比
- 序列化 Activity之间进行数据传输 List<Object> Parcelable serializable两种方式
- The Java™ Tutorials — Concurrency :Thread Objects 线程对象
- Objective-C简介
- Attaching the Filter Device Object to the Target Device Object
- iOS开发--1【Objective-C】
- 【慕课笔记】U3 继承 第7节 JAVA中的Object类(二)
- 【慕课笔记】U3 继承 第6节 JAVA中的Object类(一)
- Scala 中object和class的区别
- NSGAIII中的normalization objectives
- (object sender, EventArgs e)中的sender 和e有什么用呀?
- Objective-C Runtime系统
- JS调试输出Object
- 线程和QObjects
- ZwQuerySymbolicLinkObject routine
- ZwOpenSymbolicLinkObject routine
- IOS学习第十一天 OC语言的学习 Objective-C简介
- 百度对象存储BOS(Baidu Object Storage)进行冷存储数据备份
- JavaScript菜鸟教程Object2