写点什么

Qt | 关于对象树和元对象的相关问题

作者:YOLO.
  • 2022 年 9 月 07 日
    河北
  • 本文字数:1295 字

    阅读完需:约 4 分钟

Qt | 关于对象树和元对象的相关问题

前言:

Qt 中使用对象树来组织和管理所有的 QObject 类及其子类的对象。对象树是一个抽象概念,即所有的 QObject 对象的父子关系通过树结构来表现它们的层级关系。

Qt 中的元对象系统(Meta-Object System)提供了对象间通信的信号和槽机制运行时类型信息动态属性系统。元对象(meta object)意思是描述另一个对象结构的对象,比如获得一个对象有多少成员函数,有哪些属性。

对象树:

问题:在 Qt 中经常看到使用 new 创建了对象,但是没有使用 delete 销毁对象的用法,这样不会造成内存泄露吗?

答案: 当创建一个 QObject 对象时,如果使用了其他的 Object 对象作为其父对象,那么这个 QObject 就会被添加到父对象的 children()类表中。当父对象被销毁时,这个 QObject 也会被销毁。因此,当点击子部件的关闭时,子部件只是隐藏,而当父部件进行销毁时,子部件就会被父部件销毁,不会造成内存泄漏。

注意:

  • Qt 中的 main()函数中的主窗口部件要创建在栈上,这样在关闭程序时主窗口对象会自动销毁。

  • 对于其它窗口部件,可以使用 new 操作符在堆上进行创建,这时要指定父部件,在父部件销毁时就会将它销毁,不需要使用 delete 操作符销毁。如果没有指定父部件,也不是顶层窗口,需要使用 delete 操作符进行销毁。

元对象:

问题:moc 文件是如何生成的?

答案:对象编译器 Meta-Object Compiler 工具读取一个 C++源文件,如果它发现一个或者多个类的声明中包含 Q_OBJECT 宏,则会另外创建一个 C++源文件(就是项目中的 moc 开头的.cpp 文件)。其中包含了为每一个类生成的元对象代码。

moc 的实现是一个预处理器,使用 moc 的方式,所有平台上的标准的 C++编译器都能支持 Qt。从而不需要实现一个新的跨平台的 Qt 编译器。moc 是为了解决反射问题的,但是一些动态的编程语言(如 Python,Ruby 等)中,语言本身自带反射功能。Qt 程序之所以编译速度慢,主要是因为在 Qt 将源代码交给标准 C++编译器,如 gcc 之前,需要事先将这些扩展的语法去除掉。完成这一操作的就是 moc。

元对象系统主要是为了实现信号和槽机制才被引入的,不过除了信号和槽机制以外,元对象系统还提供了一些其他特性:

  • QObject::metaObject(): 返回一个类的元对象。

  • QMetaObject::className(): 在运行时以字符串形式返回类名。

  • QObject::inherits(): 返回一个对象是否是 QObject 继承树上一个类的实例的信息。

  • QObject::tr()和 QObject::trUtf8(): 进行字符串翻译来实现国际化。

  • QObject::setProperty()和 QObject::property(): 通过名字来动态设置或者获取对象属性。

  • QMetaObject::newInstance(): 构造类的一个实例。

  • qobject_cast(): 对 QObject 类进行动态类型转换。这个函数类似于 C++中的 dynamic_cast()函数,但它不再需要 RTTI 的支持。这个函数尝试将它的参数转换为尖括号中的类型的指针,如果是正确类型,则返回一个非零的指针;否则返回 0。

例如:

QObject *obj = new MyWidget;QWidget *widget = qobject_cast<QWidget *>(obj);
复制代码

注意, 元对象系统是基于以下 3 个条件的:

  • 该类必须继承自 QObject 类;

  • 必须在类的私有声明区声明 Q_OBJECT 宏(在类定义时,如果没有指定 public 或者 private,则默认为 private);

  • 元对象编译器 Meta-Object Compiler(moc)为 QObject 的子类实现元对象特征提供必要的代码。

发布于: 刚刚阅读数: 4
用户头像

YOLO.

关注

还未添加个人签名 2022.05.06 加入

还未添加个人简介

评论

发布
暂无评论
Qt | 关于对象树和元对象的相关问题_qt_YOLO._InfoQ写作社区