Qt是基于C++的跨平台图形界面(GUI)开发框架,简单说就是给C++开发者准备的"开发工具箱+底层封装库",让C++能高效做界面、写跨平台程序,不用为Windows/ Linux/ 嵌入式等系统单独写代码。
启用C++继承特性时,要让子类对象能使用父类对象的 this 指针,有点类似双内存空间链表链接。
- 子类需要调用父类的成员(非 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:this 在 main 里能用吗?
-
不能。
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 特性。即使你暂时不用,也要写上,否则可能编译出错。
- new ParentClass(nullptr)
→ 调用 QObject(nullptr) 构造
→ ParentClass 构造完成
- new ChildClass(parent)
→ 调用 QObject(parent) 构造,设置 Qt 父子关系
→ 初始化 m_parent = parent
→ ChildClass 构造完成
- child->useParent()
→ 判断 m_parent 不为空
→ 调用 m_parent->parentMethod()
→ 打印信息
- 程序结束,delete parent
→ Qt 自动删除 parent 的所有子对象(包括 child)
→ 先析构 child,再析构 parent
- 利用 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 指针