目录
——对象树案例
——特殊情况
GUI
GUI(graphical user interface): 图形用户接口 (界面)
指一种以图形为基础的人机交互模式。
与通常的命令符或文本控制不同。gui的界面使用户看到的都是标准化、人性化的图形对象,用户只需要通过一个个窗口就可以凭借常识完成自己希望的操作。
——————————————————————————————————
QPushButton类的操作示范:
QPushButton *window1 = new QPushButton; //两种初始化方式
window1->setParent(this);
window1->setText("保存");
QPushButton *window2 = new QPushButton("关闭",this);
window1->move(0,0); //按钮设置
window1->resize(60,30);
window2->move(60,0);
window2->resize(60,30);
setFixedSize(300,300); //固定高度
setWindowTitle("窗口名称是什么"); //窗口栏名称
window1->show();
window2->show();
myPushButton *window3 = new myPushButton;
window3->setText("myPushButton");
window3->setParent(this); //这里的parent 和继承的父类
window3->move(120,0);
window3->resize(90,30);
window3->show();
// window3 可以看出只要指定了对象树(这里其父是mywindow)就不需
——————————————————————————————
对象树
对象树的作用在我们创建对象时的parent指针可以看出。可以把这棵树看成一个家谱,把不同类的长幼关系安排清楚。
QObject类 的对象创造时,会在构造函数时接收一个parent指针作为参数,即父对象指针。
如以QObject为基类的对象树组织起来,当QObject被释放,它的所有子类(即直接或间接的 setparent(QObject) 对象 )都会被自动释放。
但这仅仅是从功能上而言。本质上 父子对象 和 C++正常继承的父类子类关系 没有任何联系。
对象树案例
自己创建一个按钮类:myPushButton 来试验对象树释放的特性
这里的 myPushButton 是以 QWidget 为基类的
mypushbutton.cpp
#include "mypushbutton.h"
#include<QDebug> //宏,返回临时对象
//指针不必要改成父类 是因为其父类QPBt的参数指针同样是 QWidget类型 //相当于在"一串"对象树上
myPushButton::myPushButton(QWidget *parent) : QPushButton(parent)
{ //parent交给父类构造。其父类QPBt默认构造为有参,需要传参数完成对象树构建
qDebug("myPusButton 构造");
};
myPushButton::~myPushButton()
{
qDebug("myPushButton 析构");
//先打印,不释放,逐层向下观察
}
mypushbutton.h 包含 QPushButton头文件
创建对象在堆区,而该对象已指定好了父亲(setParent),只要把其父辈释放析构,接下来的字辈会随之释放。有智能指针的感觉,像监护人一样。这样在一定程度上简化了内存回收机制。
当然,你可以自己手动删除某个子类,它和它下面的一系列子类会自动从父类的析构名单中消失。
特殊情况
刚刚一直在聊堆区析构,下面来探索一下栈区析构。
mywindow w;
QPushButton p("Button1",&w);
正常栈区创建,mywindow和QPB都是 QObject 的子类;
由C++的特性可知,析构顺序与他们的构造顺序相反。
此时换一个构造顺序
QPushButton p("Button1");
mywindow w;
p.setParent(&w);
我们发现程序异常结束了—— 作为父指针的mywindow后创建,先析构;可由于对象树特性,mywindow会调用每一个子指针的析构函数,所以在mywindow析构过程中,p已经析构了。
那么mywindow析构结束,p先创建,还是要在最后析构,这样就析构了两次。
所以这就不难理解为什么出现问题了。
由这个特殊情况,我们总结:①构造对象时便指定好父对象(parent指针) ② 大胆在堆上创建对象