qt元对象系统简介

在 Qt 助手的索引里面输入“The Meta-Object System”,就可以看到元对象系统的英文文档。现在将其主要的内容描述如下:
Qt 元对象系统实现了对象之间通信机制——信号和槽,并提供了运行时类型信息和动态属性系统。元对象系统是 Qt 类库独有的功能,是 Qt 对标准 C++ 的扩展,并且元对象系统本身也是由纯 C++ 语言写成的,所以学好 C++ 是必须的。
使用元对象系统的前提是需要三件事情:

  • ①直接或间接地以 QObject 为基类,这样才能利用元对象系统的功能,Qt 的窗体和控件最顶层的基类都是 QObject。
  • ②将 Q_OBJECT 放在类声明的私有段落,以启用元对象特性,如动态属性、信号和槽等。之前遇到的例子 Q_OBJECT 都是在类声明里的第一行,没有加 private 字样,因为类声明默认就是私有的。
  • ③元对象编译器(Meta-Object Compiler,moc)为每个 QObject 的子类提供必要的代码以实现元对象特性。

moc 工具读取 C++ 源码,找到一个或多个包含 Q_OBJECT 宏的类声明,然后生成额外的代码文件,如 moc_widget.cpp ,里面包含实现元对象系统的代码。生成的源码文件可以包含在类原有的源文件里,如在 widget.cpp 里包含:
#include "moc_widget.cpp"
这种包含方式看起来比较别扭,Linux 上的开发工具 KDevelop 自动生成的代码是这么用的。
第二种方式是编译链接时揉到一起,QtCreator 生成的代码就是通过编译链接时,把 moc_widget.o 与其他目标文件链接到一起,这种方式不用改源代码,相对而言比较顺眼。

除了提供信号和槽机制用于对象之间的通信(这是主要任务),元对象系统还提供了更多的特性:

  • QObject::metaObject() 函数返回当前类对象关联的元对象(meta-object)。
  • QMetaObject::className() 函数返回当前对象的类名称字符串,而不需要 C++ 编译器原生的运行时类型信息(run-time type information,RTTI)支持。
  • QObject::inherits() 函数判断当前对象是否从某个基类派生,判断某个基类是否位于从 QObject 到对象当前类的继承树上。
  • QObject::tr() 和 QObject::trUtf8() 函数负责翻译国际化字符串,因为 Qt5 规定源文件字符编码是 UTF-8,所以这两个函数现在功能是一样的。
  • QObject::setProperty() 和 QObject::property() 函数用于动态设置和获取属性,都通过属性名称字符串来 操作。
  • QMetaObject::newInstance() 构建一个当前类的新实例对象。

元对象系统还提供了 qobject_cast() 函数,可以对基于 QObject 的类对象进行转换,qobject_cast() 函数功能类似标准 C++ 的 dynamic_cast()。当然 qobject_cast() 的优势在于不需要编译器支持 RTTI,而且跨动态链接库之间的转换也是可行的。简单地说,原本是派生类的对象指针,就可以转为基类对象指针来用(转换得到可用值),其他情况都会得到 NULL 指针。比如:
MyWidget 是 QWidget 的派生类,并且类声明带有 Q_OBJECT 宏,新建一个对象:
QObject *obj = new MyWidget;
虽然 obj 是一个 QObject *,但它本质是一个 MyWidget 对象指针,可以转成基类指针:
QWidget *widget = qobject_cast<QWidget *>(obj);

但是如果将 MyWidget 对象指针转成其他无关的类对象指针,就会失败:
 QLabel *label = qobject_cast<QLabel *>(obj);
label的数值就是 NULL。

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

yxkfw

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值