日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

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

發(fā)布時間:2025/3/15 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Qt文档阅读笔记-Object Trees Ownership解析与实例(为何某些程序在被关闭的时候会崩溃) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

目錄

官方解析

Construction/Destruction Order of QObjects

博主栗子

繼承里面構(gòu)造函數(shù)與析構(gòu)函數(shù)的順序

在Qt中,object trees里面的創(chuàng)建與析構(gòu)

【重要實例】在棧區(qū)創(chuàng)建的時候,就有問題了


官方解析

每一個QObject都有自己的一顆對象樹。當你創(chuàng)建一個QObject對象,并且另一個對象作為他的parent的時候,這個新創(chuàng)建的對象就會被添加到父類的children()list中,當parent被刪除的時候他的children都會被刪除。這種方式對GUI對象是十分有用的【從這里可以知道,當要對GUI進行操作的時候,優(yōu)先考慮設(shè)置parent,因為界面被刪除的時候,控件也會被刪除,其他成員得自己去delete】。舉個栗子,QShortcut類創(chuàng)建的對象是某一個窗口的child,當這個窗口被關(guān)閉后,這個類的對象也會被Delete掉。

QQuickItem這個玩意是Quick module的最基礎(chǔ)的視覺元素,并且他也是QObject的派生類,不過,visual parent與傳統(tǒng)控件里面的QObject parent概念不同。一個item的visual parent不一定與object parent相同。相關(guān)細節(jié)查看Concepts - Visual Parent in Qt Quick。

QWidget是最基礎(chǔ)的Qt Widgets module 類,這個類擴展了parent-child的關(guān)系。他的child通常可以看做他的子部件,子窗口等。QWidget里面的這些child顯示于他的parent坐標系并且他的形狀受他parent的邊界的影響【一般情況下是這樣,但如果有布局,就會受到布局的影響】。舉個栗子,當這個程序被關(guān)閉后,填出一個delete的Messagebox,這個Messagebox的按鈕和標簽都會被刪除,當然這是你設(shè)置了parent的情況下才會,設(shè)置了才會刪除,沒設(shè)置就不會被刪除。

你可以自己手動delete某個對象樹中的子對象,如果刪除掉,他也會自動從他的parent中的child中刪除,舉個栗子,當移除toolbar后會導致應(yīng)用程序刪除QToolBar這個類對應(yīng)的對象,在這種情況下QMainWindow將檢查并且改變程序的屏幕位置。

當一個程序的外觀或行為異常的時候,調(diào)試功能QObject::dumpObjectTree()和QObject::dumpObjectInfo()將十分有效。

Construction/Destruction Order of QObjects

當在堆區(qū)創(chuàng)建了許多QObjects對象的時候,對象樹會以任意的順序被創(chuàng)建,之后他們會以任意的順序銷毀。如果這個對象有parent,析構(gòu)的時候就會自動從他的parent中移除。如果這個對象有children,析構(gòu)這個對象的時候他會自動析構(gòu)他的每一個child,無論銷毀順序如何,他都不會調(diào)用兩次。

當對象們在棧區(qū)創(chuàng)建的時候,上述的行文同樣適合,通常析構(gòu)的順序不會帶來什么問題。,可以參考下如下的代碼段:

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


parent和child都是QObject對象,因為QPushButton繼承于QWidget,而QWidget繼承于QObject。這個代碼是正確的:在quit被銷毀的時候不會調(diào)用兩次,因為C++11指出創(chuàng)建對象的順序,與析構(gòu)的順序相反。因此當child被析構(gòu)后quit先會被析構(gòu),然后從他的parent里面把他給移除,然后再析構(gòu)這個windows對象。

現(xiàn)在考慮下交換構(gòu)造順序,將發(fā)送什么問題,如下面這段代碼:

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


在這種情況下,析構(gòu)就會導致一個問題,quit的parent先會被調(diào)用,因為他后被創(chuàng)建。然后再銷毀他的子對象quit,這樣做是不準確的,因為quit是本地變量。當quit被銷毀后,他的析構(gòu)函數(shù)又被調(diào)用了一次,這一次才正常的調(diào)用,不過這可能會導致程序的崩潰!

?

博主栗子
?

繼承里面構(gòu)造函數(shù)與析構(gòu)函數(shù)的順序

運行截圖如下:

源碼如下:

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里面的創(chuàng)建與析構(gòu)

運行截圖如下:

源碼如下:

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(); }

?

【重要實例】在棧區(qū)創(chuàng)建的時候,就有問題了

運行截圖如下:

源碼如下:

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(); }

這個原因是,只有手動刪除的時候(在堆區(qū)創(chuàng)建的才能手動刪除),才會把parent中的對應(yīng)自己的child刪除,在棧中都是系統(tǒng)調(diào)用,沒有這種機制!!,這樣就會調(diào)用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(); }

運行截圖如下:

總結(jié)

以上是生活随笔為你收集整理的Qt文档阅读笔记-Object Trees Ownership解析与实例(为何某些程序在被关闭的时候会崩溃)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。