[QT]Qt对象树笔记:父子关系与内存管理

Qt是基于C++的跨平台图形界面(GUI)开发框架,简单说就是给C++开发者准备的"开发工具箱+底层封装库",让C++能高效做界面、写跨平台程序,不用为Windows/ Linux/ 嵌入式等系统单独写代码。

启用C++继承特性时,要让子类对象能使用父类对象的 this 指针,有点类似双内存空间链表链接。

  1. 子类需要调用父类的成员(非 Qt 对象树),直接分配指针对象,但是破坏了父子类之间的封装特性。如果两个类没有继承关系,只是想让子类持有父类的指针来调用方法,可以在子类中定义一个成员变量来保存父类的 this:

class ParentClass : public QObject {

Q_OBJECT

public:

void createChild() {

// 将父类自己的 this 传给子类

child = new ChildClass(this);

}

private:

ChildClass *child;

};

class ChildClass : public QObject {

Q_OBJECT

public:

explicit ChildClass(ParentClass *parent = nullptr)

: QObject(parent), m_parent(parent) {}

void useParent() {

if (m_parent) {

m_parent->parentMethod(); // 调用父类方法

}

}

private:

//创建私有父类指针,用于调用父类方法

ParentClass *m_parent;

};

// 使用时

ParentClass *parent = new ParentClass(this);

MyChild *child = new MyChild(parent); // 自动保存 parent 指针

Q1:为什么要保存 m_parent?直接用 parent() 不行吗?

  • parent() 返回的是 QObject*,只能调用 QObject 的方法。而你想调用 ParentClass 特有的 parentMethod(),所以需要 ParentClass* 类型的指针。

  • 你可以用 qobject_cast<ParentClass*>(parent()) 转换,但每次都写麻烦,而且可能失败。保存 m_parent 更直接。

Q2:thismain 里能用吗?

  • 不能。main 函数不是类的成员函数,没有 this。所以示例最后一行中的 this 是错误的,应该改为 nullptr 或者一个真实存在的 QObject 指针。

  • 正确写法:

    cpp

    复制代码
    // 在 main 函数中
    ParentClass *parent = new ParentClass(nullptr);  // 顶层对象,无父对象
    ChildClass *child = new ChildClass(parent);

Q3:explicit 关键字有什么用?

  • 防止编译器自动隐式转换。比如你写 ChildClass child = parent; 会编译报错,必须显式写成 ChildClass child(parent);。这能避免不经意间的错误转换。

Q4:Q_OBJECT 宏是干嘛的?

  • 必须写在继承 QObject 的类的最开头,才能使用信号槽、动态属性等 Qt 特性。即使你暂时不用,也要写上,否则可能编译出错。
  1. new ParentClass(nullptr)

→ 调用 QObject(nullptr) 构造

→ ParentClass 构造完成

  1. new ChildClass(parent)

→ 调用 QObject(parent) 构造,设置 Qt 父子关系

→ 初始化 m_parent = parent

→ ChildClass 构造完成

  1. child->useParent()

→ 判断 m_parent 不为空

→ 调用 m_parent->parentMethod()

→ 打印信息

  1. 程序结束,delete parent

→ Qt 自动删除 parent 的所有子对象(包括 child)

→ 先析构 child,再析构 parent

  1. 利用 Qt 对象树(推荐),Qt 标准做法,能自动管理生命周期(父对象销毁时子对象也会被销毁),但获取时需要用 qobject_cast 转型。如果子类继承自 QObject,可以在构造时直接传入父对象的 this,Qt 会自动管理父子关系,子类可通过 parent() 获取父类指针:

class MyChild : public QObject {

Q_OBJECT

public:

explicit MyChild(QObject *parent = nullptr) : QObject(parent) {}

void useParent() {

// 通过 parent() 获取父对象,需转型为实际的父类类型

ParentClass *p = qobject_cast<ParentClass*>(parent());

if (p) {

p->parentMethod();

}

}

};

// 使用时

ParentClass *parent = new ParentClass(this);

MyChild *child = new MyChild(parent); // 自动保存 parent 指针

相关推荐
用户805533698031 天前
不止三件套:QObject 属性系统全关键字与运行时反射!
c++·qt
xcyxiner1 天前
DicomViewer (vcpkg Windows和ubuntu编译)7
qt
Quz6 天前
QML Hello World 入门示例
qt
xcyxiner9 天前
DicomViewer (dcmtk读取dcm文件)5
qt
xcyxiner10 天前
DicomViewer (后台线程处理文件)4
qt
xcyxiner10 天前
DicomViewer (添加模型类)3
qt
xcyxiner11 天前
DicomViewer (目录调整) 2
qt
xcyxiner11 天前
dcmtk vtk vtk-dicom(gdcm) 编译(debug) v2
qt
LDR00613 天前
Type-C 快充全面升级!LDR6601 赋能个人护理便携电机,重塑剃须刀 / 理发器新体验
c语言·开发语言
雪碧聊技术13 天前
Tree.js是什么?一文讲透
开发语言·javascript·ecmascript