[学习][笔记] qt5 从入门到入坟:<四>对象模型

简介: [学习][笔记] qt5 从入门到入坟:<四>对象模型

对象模型

moc (Meta Object Compiler,元对象编译器)

moc 为了解决某些特定问题域下的静态特性 和 GUI 界面需要同时具有运行时的效率以及更高级别的灵活性。

Qt “扩展”了标准C++。所谓“扩展”,实际是在使用标准 C++ 编译器编译 Qt 源程序之前,Qt 先使用一个叫做 moc(Meta ObjectCompiler,元对象编译器)的工具,先对 Qt 源代码进行一次预处理(注意,这个预处理与标准 C++ 的预处理有所不同。Qt 的 moc预处理发生在标准 C++ 预处理器工作之前,并且 Qt 的 moc 预处理不是递归的。),生成标准 C++ 源代码,然后再使用标准 C++编译器进行编译。

例如信号槽,c++标准不支持的但是却可以编译通过。

Qt 使用 moc,为标准 C++ 增加了一些特性:

信号槽机制,用于解决对象之间的通讯,这个我们已经了解过了,可以认为是 Qt 最明显的特性之一; 可查询,并且可设计的对象属性;

强大的事件机制以及事件过滤器; 基于上下文的字符串翻译机制(国际化),也就是 tr() 函数,我们简单地介绍过;

复杂的定时器实现,用于在事件驱动的 GUI 中嵌入能够精确控制的任务集成; 层次化的可查询的对象树,提供一种自然的方式管理对象关系。

智能指针(QPointer),在对象析构之后自动设为 0,防止野指针; 能够跨越库边界的动态转换机制。

通过继承QObject类,我们可以很方便地获得这些特性。 当然,这些特性都是由 moc 帮助我们实现的。moc

其实实现的是一个叫做元对象系统(meta-object system)的机制。正如上面所说,这是一个标准 C++ 的扩展,使得标准 C++

更适合于进行 GUI 编程。虽然利用模板可以达到类似的效果,但是 Qt 没有选择使用模板。按照 Qt

官方的说法,模板虽然是内置语言特性,但是其语法实在是复杂,并且由于 GUI 是动态的,利用静态的模板机制有时候很难处理。而自己使用 moc

生成代码更为灵活,虽然效率有些降低(一个信号槽的调用大约相当于四个模板函数调用),不过在现代计算机上,这点性能损耗实在是可以忽略。

对象树

QObject

QObject是以对象树的形式建立的,QObject对象创建的时候,构造方法需要传入parent,当前QObject作为该parent的children其中的一个孩子。当parent销毁时parent的children也会销毁。

例如,一个QButton(按钮)有一个QShortcut(快捷键)对象作为其子对象。当我们删除按钮的时候,这个快捷键理应被删除。这是合理的。

对于控件QWindow和QDialog 如果parent 为 NULL,则该对话框会作为一个顶层窗口,否则则作为其父组件的子对话框。

QWidget

QWidget是能够在屏幕上显示的一切组件的父类。QWidget继承自QObject,因此也继承了这种对象树关系。一个孩子自动地成为父组件的一个子组件。因此,它会显示在父组件的坐标系统中,被父组件的边界剪裁。例如,当用户关闭一个对话框的时候,应用程序将其删除,那么,我们希望属于这个对话框的按钮、图标等应该一起被删除。事实就是如此,因为这些都是对话框的子组件。

当然,我们也可以自己删除子对象,它们会自动从其父对象列表中删除。比如,当我们删除了一个工具栏时,其所在的主窗口会自动将该工具栏从其子对象列表中删除,并且自动调整屏幕显示。

我们可以使用QObject::dumpObjectTree()和QObject::dumpObjectInfo()这两个函数进行这方面的调试。

Qt 的对象树机制虽然帮助我们在一定程度上解决了内存问题,但是也引入了一些值得注意的事情。

当一个QObject对象在堆上创建的时候,Qt 会同时为其创建一个对象树。

不过,对象树中对象的顺序是没有定义的。这意味着,销毁这些对象的顺序也是未定义的。

Qt 保证的是,任何对象树中的 QObject对象delete 的时候,如果这个对象有 parent,则自动将其从 parent 的children()列表中删除;如果有孩子,则自动delete 每一个孩子。Qt 保证没有QObject会被 delete 两次,这是由析构顺序决定的。

当一个QObject对象在栈上创建的时候,就需要注意父子创建顺序问题。

{
    QWidget window;
    QPushButton quit("Quit", &window);
}

解释以上:windows先创建后销毁,quit后创建先销毁调用析构,将自己从父对象 window 的子对象列表中删除,然后再销毁windows,调用windows析构。不会造成quit析构两次问题。

但是下面:

{
    QPushButton quit("Quit");
    QWidget window;
    quit.setParent(&window);
}

quit先创建后销毁,window后创建先销毁,window销毁时调用析构时会先析沟子对象列表。然后quit又一次因为超出作用域而析构时,会造成第二次析沟导致问题。

Qt 学习之路 2(10):对象模型

相关文章
|
28天前
|
XML 开发框架 JSON
【Qt】Qt入门
【Qt】Qt入门
|
2月前
|
存储 安全 Java
Qt线程池+生产者消费者模型
Qt线程池+生产者消费者模型
59 5
|
2月前
【qt】标准项模型1
【qt】标准项模型
20 0
|
18天前
|
编译器 C++
(10)Qt对象模型
(10)Qt对象模型
|
24天前
|
前端开发
自定义QT QWidget对象响应弹出菜单的解决方法
自定义QT QWidget对象响应弹出菜单的解决方法
26 1
|
4天前
|
XML 存储 JSON
技术笔记:Qt基础之配置文件(QSettings)
技术笔记:Qt基础之配置文件(QSettings)
|
24天前
|
计算机视觉
【轻松入门】OpenCV4.8 + QT5.x开发环境搭建
【轻松入门】OpenCV4.8 + QT5.x开发环境搭建
16 0
【轻松入门】OpenCV4.8 + QT5.x开发环境搭建
|
4天前
|
调度
技术笔记:QT之深入理解QThread
技术笔记:QT之深入理解QThread
|
2月前
|
监控 数据可视化 Linux
Qt Model&View&Delegate(模型-视图-代理) 介绍和使用
Qt Model&View&Delegate(模型-视图-代理) 介绍和使用
Qt Model&View&Delegate(模型-视图-代理) 介绍和使用
|
2月前
|
索引
【qt】标准型模型 下
【qt】标准型模型 下
8 0

推荐镜像

更多