铅笔

在你的害怕中坚持的越多,你就会越自信
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

Qt 对象间的父子关系

Posted on 2017-01-08 20:36  黑色の铅笔  阅读(5428)  评论(0编辑  收藏  举报

C++中只要有一个new就必须要有一个delete与之对应

但是Qt中的对象之间有特殊的关系

 

 

Qt 对象间的父子关系

每一个对象都保存有它所有子对象的指针

每一个对象都有一个指向其父对象的指针

parent里面有个链表 链表的每一个元素都是就是指向子对象的 指针

  类似的每一个子对向都保存了一个指向父对象的指针

 

Qt中的对象如何指定其父对象?

成员函数:setparent;

 

 当调用setparent函数时,父对象将子对像加入到自己的链表中,子对像将一个指针指向父对象,这样对象就产生了父子关系。

 

为证明上述新建一个控制台的应用程序

  

#include <QCoreApplication>
#include <QDebug>
void fcTest()
{
    QObject* p = new QObject();
    QObject* c1 = new QObject();
    QObject* c2 = new QObject();

    c1->setParent(p);//该函数执行后p执行那个的对象就变成了父类的对象
    c2->setParent(p);

    qDebug() << "c1: " << c1;//输出c1对象的地址
    qDebug() << "c2: " << c2;

    const QObjectList& list = p->children();

    for(int i=0; i<list.length(); i++)//Qt中提供了想访问数组的方式访问这个链表
    {
        qDebug() << list[i];
    }

    qDebug() << "p: " << p;

    qDebug() << "c1 parent: " << c1->parent();//函数返回父对象的指针
    qDebug() << "c2 parent: " << c2->parent();
}

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    fcTest();
    return a.exec();
}

 如果对代码中的成员函数不理解可以到Qt的帮助文档中直接找其说明

方法:1、搜索QObject类

        2、在该类的成员函数中找对应的函数了即可得到该函数的说明:Makes the object a child of parent.即指定一个对象的父类。

对于const QObjectList& list = p->children();同样使用上面Qt中的文档找到:

const QObjectList & QObject::​children() const

Returns a list of child objects. The QObjectList class is defined in the <QObject> header file as the following:

 typedef QList<QObject*> QObjectList;

可以知道该函数的返回值const QObjectList &类型的链表

其中QObjectList 又是一个 QList<QObject*>  即是一个链表,链表中的元素又是QObject对象类型指针

 

 

Qt对象销毁时又会有那些事情?

当Qt对象被销毁时,很有可能不止一个对象被销毁,因为其销毁时,会将该对象的子对象链表中的所有对象都销毁。

 

 

 通过setparent就可以形成上面的对象数,当删除obj3时,其子类obj4的对象也要会销毁。

 

为证明上面的结论:

创建一个继承QObject的类

 1 class MObj:public QObject
 2  {
 3 
 4     QString m_name;
 5  public:
 6      MObj(const QString& name)
 7     {
 8         m_name=name;
 9         qDebug()<<"Constructor:"<<m_name;
10       }
11 
12      ~MObj()
13      {
14      qDebug() << "Destructor: " << m_name;
15     }
16  };

测试函数:

 void delTest()
 {
     MObj* obj1=new MObj("obj1");
    MObj* obj2=new MObj("obj2");
     MObj* obj3=new MObj("obj3");
     MObj* obj4=new MObj("obj4");
    //构建对象数
     obj2->setParent(obj1);
     obj3->setParent(obj1);
     obj4->setParent(obj3);
 
     //删除obj3
     delete obj3;
   
 //delete obj4;如果再次delete obj4就会出错,
    //由于obj4已经被delete了,此时obj4是一个野指针,delete野指针肯定会内存出错的
 }

 

完整代码:

 1 #include <QCoreApplication>
 2 #include <QDebug>
 3 #include <QString>
 4 
 5 class MObj:public QObject
 6  {
 7     
 8     QString m_name;
 9  public:
10      MObj(const QString& name)
11     {
12         m_name=name;
13         qDebug()<<"Constructor:"<<m_name;
14       }
15      ~MObj()
16      {
17      qDebug() << "Destructor: " << m_name;
18     }
19  };
20 void delTest()
21 {
22     MObj* obj1=new MObj("obj1");
23     MObj* obj2=new MObj("obj2");
24     MObj* obj3=new MObj("obj3");
25     MObj* obj4=new MObj("obj4");
26     //构建对象数
27     obj2->setParent(obj1);
28     obj3->setParent(obj1);
29     obj4->setParent(obj3);
30     //删除obj3
31     delete obj3;
32 }
33 int main(int argc, char *argv[])
34 {
35     QCoreApplication a(argc, argv);
36     delTest();
37     return a.exec();
38 }
View Code

 

结果:

可以看到析构函数被调用了两次,包括obj4和obj3

 

小结:

 

 

 

 

 学习狄泰软件Qt实验教程学习笔记16课