目录

官方解析

Construction/Destruction Order of QObjects

博主栗子

继承里面构造函数与析构函数的顺序

在Qt中,object trees里面的创建与析构

【重要实例】在栈区创建的时候,就有问题了


官方解析

每一个QObject都有自己的一颗对象树。当你创建一个QObject对象,并且另一个对象作为他的parent的时候,这个新创建的对象就会被添加到父类的children()list中,当parent被删除的时候他的children都会被删除。这种方式对GUI对象是十分有用的【从这里可以知道,当要对GUI进行操作的时候,优先考虑设置parent,因为界面被删除的时候,控件也会被删除,其他成员得自己去delete】。举个栗子,QShortcut类创建的对象是某一个窗口的child,当这个窗口被关闭后,这个类的对象也会被Delete掉。

QQuickItem这个玩意是Quick module的最基础的视觉元素,并且他也是QObject的派生类,不过,visual parent与传统控件里面的QObject parent概念不同。一个item的visual parent不一定与object parent相同。相关细节查看Concepts - Visual Parent in Qt Quick。

QWidget是最基础的Qt Widgets module 类,这个类扩展了parent-child的关系。他的child通常可以看做他的子部件,子窗口等。QWidget里面的这些child显示于他的parent坐标系并且他的形状受他parent的边界的影响【一般情况下是这样,但如果有布局,就会受到布局的影响】。举个栗子,当这个程序被关闭后,填出一个delete的Messagebox,这个Messagebox的按钮和标签都会被删除,当然这是你设置了parent的情况下才会,设置了才会删除,没设置就不会被删除。

你可以自己手动delete某个对象树中的子对象,如果删除掉,他也会自动从他的parent中的child中删除,举个栗子,当移除toolbar后会导致应用程序删除QToolBar这个类对应的对象,在这种情况下QMainWindow将检查并且改变程序的屏幕位置。

当一个程序的外观或行为异常的时候,调试功能QObject::dumpObjectTree()和QObject::dumpObjectInfo()将十分有效。

Construction/Destruction Order of QObjects

当在堆区创建了许多QObjects对象的时候,对象树会以任意的顺序被创建,之后他们会以任意的顺序销毁。如果这个对象有parent,析构的时候就会自动从他的parent中移除。如果这个对象有children,析构这个对象的时候他会自动析构他的每一个child,无论销毁顺序如何,他都不会调用两次。

当对象们在栈区创建的时候,上述的行文同样适合,通常析构的顺序不会带来什么问题。,可以参考下如下的代码段:

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

parent和child都是QObject对象,因为QPushButton继承于QWidget,而QWidget继承于QObject。这个代码是正确的:在quit被销毁的时候不会调用两次,因为C++11指出创建对象的顺序,与析构的顺序相反。因此当child被析构后quit先会被析构,然后从他的parent里面把他给移除,然后再析构这个windows对象。

现在考虑下交换构造顺序,将发送什么问题,如下面这段代码:

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

在这种情况下,析构就会导致一个问题,quit的parent先会被调用,因为他后被创建。然后再销毁他的子对象quit,这样做是不准确的,因为quit是本地变量。当quit被销毁后,他的析构函数又被调用了一次,这一次才正常的调用,不过这可能会导致程序的崩溃!

博主栗子

继承里面构造函数与析构函数的顺序

运行截图如下:

源码如下:

main.cpp

#include <iostream>
using namespace std;class Base {
public:virtual void print() {cout << "Base print called!\n";}Base() {cout << "Base construction called!\n";}~Base() {cout << "Base deconstruction called!\n";}
};class Child1 :public Base {
public:void print() {cout << "Child1 print called!\n";Base::print();}Child1() {cout << "Child1 construction called!\n";}~Child1() {cout << "Child1 construction called!\n";}
};class Child2 :public Base {
public:void print() {cout << "Child2 print called!\n";}Child2() {cout << "Child2 construction called!\n";}~Child2() {cout << "Child2 deconstruction called!\n";}
};void  main() {Child1 *child1 = new Child1;delete child1;getchar();
}

在Qt中,object trees里面的创建与析构

运行截图如下:

源码如下:

democlass.h

#ifndef DEMOCLASS_H
#define DEMOCLASS_H#include <QObject>class Base : public QObject
{//Q_OBJECT      to use object tree without singals and slots. so we needn't Q_OBJECT
public:Base(QObject *parent = 0);~Base();
};class Child:public QObject{
public:Child(QObject *parent=0);~Child();
};class OtherBase:public QObject{
public:OtherBase(QObject *parent=0);~OtherBase();
};#endif // DEMOCLASS_H

democlass.cpp

#include "democlass.h"
#include <QDebug>Base::Base(QObject *parent) : QObject(parent)
{qDebug()<<"Base construction called!";
}Base::~Base()
{qDebug()<<"Base deconstruction called!";
}Child::Child(QObject *parent):QObject(parent)
{qDebug()<<"Child construction called!";
}Child::~Child()
{qDebug()<<"child deconstruction called!";
}OtherBase::OtherBase(QObject *parent):QObject(parent)
{qDebug()<<"OtherBase construction called!";
}OtherBase::~OtherBase()
{qDebug()<<"otherBase deconstruction called!";
}

main.cpp

#include <QDebug>
#include <QApplication>
#include "democlass.h"int main(int argc, char *argv[])
{QApplication a(argc, argv);Base *base=new Base;Child *child_1=new Child(base);OtherBase *otherBase_1=new OtherBase(base);OtherBase *otherBase_2=new OtherBase(base);Child *child_2=new Child(child_1);base->dumpObjectTree();delete base;return a.exec();
}

【重要实例】在栈区创建的时候,就有问题了

运行截图如下:

源码如下:

democlass.h

同上

democlass.cpp

同上

main.cpp

#include <QDebug>
#include <QApplication>
#include "democlass.h"int main(int argc, char *argv[])
{QApplication a(argc, argv);{Child child;Base base;child.setParent(&base);qDebug()<<"Prepare deconstruction";}return a.exec();
}

这个原因是,只有手动删除的时候(在堆区创建的才能手动删除),才会把parent中的对应自己的child删除,在栈中都是系统调用,没有这种机制!!,这样就会调用2次Delete

所以这种代码,正确的改法如下:

#include <QDebug>
#include <QApplication>
#include "democlass.h"int main(int argc, char *argv[])
{QApplication a(argc, argv);{Base base;Child child;child.setParent(&base);qDebug()<<"Prepare deconstruction";}return a.exec();
}

运行截图如下:

Qt文档阅读笔记-Object Trees Ownership解析与实例(为何某些程序在被关闭的时候会崩溃)相关推荐

  1. Qt文档阅读笔记-Object Model初步解析

    对象模型 标准C++对象模型提供了对象范式在运行时的高效性.但是他的一些静态性质在某些领域是不灵活的.在GUI程序中不仅要运行时的高效还需要较高的灵活性.Qt对象模型不急结合了C++运行时的高效并且还 ...

  2. Qt文档阅读笔记-GridLayout QML Type解析与实例

    目录 基本概念 代码与实例 基本概念 如果QGridLaout大小被调整,所有item的布局都将会重新排列.和widget的QGridLayout一样.如果想要一行或一列的布局可以使用RowLayou ...

  3. Qt文档阅读笔记-Image QML官方解析与实例

    目录 官方解析 博主例子 官方解析 Image Image用于展示图片. 使用source属性可以使用URL指定一张图片. 只要是Qt能打开的图片都支持,如果要展示动态图,要使用:BnimatedSp ...

  4. Qt文档阅读笔记-Widgets Tutorial官方解析及实例

    目录 官方解析 博主栗子 官方解析 QWiget通常作为其他窗口的容器,可以使用QWidget到达最小代价定义自定义控件(经验:通常可以采用子类QLabel做成自定义控件) 可以通过构建他的父类对象来 ...

  5. Qt文档阅读笔记-easingCurve:QEasingCurve官方解析及实例

    目录 官方解析 博主例子 官方解析 easingCurve:QEasingCurve 这个属性保留了动画的缓和曲线. 他定义了缓和取消,默认情况下,使用线性缓和曲线,产生线性插入值.下面举出其他曲线的 ...

  6. Qt文档阅读笔记-编写应用脚本解析与实例

    目录 官方解析 博主例子 官方解析 编写应用脚本 Qt提供了JavaScript脚本对应用程序的支持.下面将全方位说明JavaScript在Qt中的应用. Scripting Classes 如下的类 ...

  7. Qt文档阅读笔记-The Meta-Object System解析及实例

    目录 官方解析 博主栗子 关于QMetaObject::className()的栗子 官方解析 Qt元对象系统提供了信号与槽机制,通过信号与槽实现对象间的通信,RTTI,以及动态属性系统. meta- ...

  8. Qt文档阅读笔记-QML RotationAnimation官方解析及实例

    目录 官方解析 博主例子 官方解析 RotationAnimation是一个属性动画,这个属性控制图片的旋转. 默认情况下,他在给定的数值方向上旋转,比如从0度顺时针旋转到240度,也可以逆时针旋转比 ...

  9. Qt文档阅读笔记-QHeaderView::sectionResized官方解析与实例

    目录 官方解析 博主例子 官方解析 不翻译了,很简单的英语 博主例子 程序运行截图如下 源码如下: widget.h #ifndef WIDGET_H #define WIDGET_H#include ...

最新文章

  1. Android下对Cookie的读写操作(附Demo)
  2. Docker安全之用户资源隔离
  3. InSAR 处理软件
  4. udf、utaf、udtf进出数量规律
  5. 天池 在线编程 推荐朋友(哈希)
  6. linux能记录日志的终端,Linux上的日志系统
  7. python discuz搜索api_Django用内置方法实现简单搜索功能的方法
  8. 【语义分割】评价指标代码函数:np.sum()、np.nansum()、np.nanmean()、np.diag()、np.bincount()
  9. 汉字转拼音,TinyPinyin、Pinyin4j与JPinyin哪个库更快
  10. 【SICP归纳】2 高阶函数和数据抽象
  11. 4 安卓安装路径_安卓逆向——APK安装流程
  12. 蛮力法求最大字段和时间复杂度_中文分词算法之--最大匹配法
  13. matlab 随机信道,随机空时无线信道模型及Matlab仿真
  14. LS-DYNA 学习总结与感悟 以EM模块为主
  15. 有关Google面试的资料集合
  16. 快递单号的正则提取试
  17. Netty in Action 中文版 --最贴近原著的翻译
  18. 深圳高中女生街头版someone like you
  19. Git 学习日记-01
  20. 前端第二章:1.HTML简介、Linux 命令行打开 .html 文件、常用标签(一)

热门文章

  1. 程序猿误区:程序员只负责编码
  2. 一个简单的录音软件程序代码【C++】
  3. dazhilu网站代码【完整篇】
  4. XEIM_跨平台的网络通信产品
  5. 编程新手选择开发语言的注意事项
  6. 入行AI,你需要一本Python机器学习入门,赶紧收藏!
  7. 关于不过洋节的通知_平安夜、圣诞节安全教育告家长通知书
  8. 使用OpenCV可视化Intel Realsensen D435 深度图为彩色图
  9. 如何保证文章中同一组样品在不同子图颜色一致?
  10. 导师没项目怎么办?不如看看这些