QT6 源(1):QObject 及其子类这样的容器对象析构时,可以顺带销毁容器中元素的原理。类源码 QObject、智能指针 QScopedPointer、元对象数据类 QObjectData

(1)在 c++ 里,我们学到的知识是在堆区创建了一个对象后,一定要记得析构它,以回收内存,防止内存泄露。若类里有一个指针成员 T * ptrT ; ,且该成员指针指向了堆区中的类对象,则一定要在析构函数里调用语句 delete ptrT ; 来回收堆区里 T 对象占据的内存。但在 QT 里, QT 大师们设计了一套源代码,以使 QT 易学易用,以支持创建更大的项目。就引入了新的对象析构规则,如题目所示。

(2)在 c++ 语言里,按约定俗成的说法,严格的来讲 class A : public B ; 。 则这才表示 B 是 A 的父类,父对象, A 与 B 之间存在构造与析构的源代码级继承关系。父子这两个汉字,这个概念,更多的是类代码的继承关系。为了避免混淆,不应该改变父子这两个字的语义。直接把父子这两个字拿到 QT 里,来表示 “父“对象析构时可以顺带销毁“子“对象 这样的说法是欠妥当的,容易引起困惑,而且也不符合 c++ 的语法规定。 QT 里要表示这个顺带析构的含义,更准确的描述,应该是 :容器对象析构时,可以顺带销毁容器中元素。而且源码显示, QObject 基类,就是容器。所以,凡是继承了 QObject 类的子类,都将具备容器属性

(3)给出 QObject 类的简化定义以及 QT 版智能指针类 QScopedPointer《T》的定义

template <typename T, 
	typename Cleanup = QScopedPointerDeleter<T> >
class QScopedPointer //本类封装了裸指针 d,模板形参 2 指出了 类型 T 的析构函数
{                    //所以从结果看,本类是类似于 STL 库里的智能指针的。
public :             //本类的作用主要是防止内存泄露,以防忘记了调用类 T 的析构函数
    explicit QScopedPointer(T *p = nullptr) noexcept : d(p) { }
    inline  ~QScopedPointer() {   Cleanup::cleanup(d);   }
    typedef T * pointer; 
    T * data() const noexcept { return d; } //返回包裹的裸指针
protected : T * d;   //本 QScopedPointer类实现于头文件 qscopedpointer.h
};                   

class Q_CORE_EXPORT QObject // export 宏表要编译本类成 dll 文件
{                           //本类定义于 头文件 qobject.h
public : //可见该形参为 QObject * 指针的有参构造函数始于本 QObject基类。
    explicit QObject(QObject * parent = nullptr); //实现保密,官方注释见后面
    void   setParent(QObject * parent);
    virtual ~QObject();    //基类的正常的虚析构函数,不违背 c++ 语法
    inline const QObjectList & children() const { return d_ptr->children; }
protected :  //该数据成员 d_ptr 是 QObject 类的唯一数据成员,并被 QObject 的子类 
    QScopedPointer<QObjectData> d_ptr;   //所继承。QObject 的子类也会有这些属性
}

(4)上面的 QObject 类有个智能指针类型的数据成员,该数据成员 d_ptr 指向堆区的 QObjectData 型数据结构 ,给出其定义。该类才描述了 QObject 具有的数据结构,并决定了 QObject 应该具有的功能。也就解释清楚了为啥 QT 里 QObject 类的子类都是容器

class Q_CORE_EXPORT QObjectData
{
    Q_DISABLE_COPY(QObjectData) //该宏表示禁止定义 copy 构造与 copy 赋值运算符函数
public:
    QObjectData() = default;
    virtual ~QObjectData() = 0;
    QObject * q_ptr ; //该成员指出本类描述的是哪个 QObject 对象,回指向 QObject 
    QObject * parent; //记录本 QObject 类的所属容器。该功能又继承给 QObject 的所有子类
    QObjectList children; //记录本 QObject 容器包含的所有 QObject 类对象
    //typedef  QList< QObject * >   QObjectList; 类型定义
    //基于此,为了处理 QT中的类对象析构,似宜将所有的类都继承 QObject并将之加入到某个容器中。

    uint isWidget : 1; //以下是记录 QObject 对象应具备的其它属性,看不懂,略
    uint blockSig : 1;
    uint wasDeleted : 1;
    uint isDeletingChildren : 1;
    uint sendChildEvents : 1;
    uint receiveChildEvents : 1;
    uint isWindow : 1; // for QWindow
    uint deleteLaterCalled : 1;
    uint unused : 24;
    int postedEvents;
    QDynamicMetaObjectData *metaObject;
    QBindingStorage bindingStorage;
    QMetaObject * dynamicMetaObject() const;

#ifdef QT_DEBUG
    enum { CheckForParentChildLoopsWarnDepth = 4096 };
#endif
};

++举例验证数据成员 q_ptr 的含义

在这里插入图片描述

(5)补充上 QObject 类型的此有参构造函数的含义

在这里插入图片描述

(6)

谢谢

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值