QT-元对象系统
元对象系统简介
Qt的元对象系统(The Meta-Object System)是Qt框架的核心特性之一,它为Qt提供了反射功能和动态属性管理。这个系统使得Qt能够在运行时
处理对象的信息和特性,支持信号与槽机制、动态属性系统、运行时识别类型信息等功能。
元对象系统基于以下3点:
- Object类:给所有使用元对象系统的对象提供了一个基类;
- Q_OBJECT:用于启用元对象特性,写在类声明的私有部分中;
- 元对象编译器moc:为每个QObject子类提供实现元对象特性所需的代码。
moc是怎么工作的?
moc读取一个c++源文件(如demo.cpp),若发现源文件中包含Q_OBJECT宏的类声明,就会生成另一个c++源文件(如moc_demo.cpp),其中包含每个类的元对象代码。生成的源文件编译并链接到类的实现中(也可以include到类的源文件中)。
QObject类
创建和销毁
QObject::QObject(QObject* parent = nullptr)
构造一个QObject对象。
- 指定父对象:对象的父对象可看作对象的所有者,当父对象被销毁时,其析构函数也会销毁所有子对象;
- 不指定父对象:即设为nullptr时,旧旧构造一个无父对象的对象,此时若对象是一个widget,则该widget将称为一个顶级窗口。
QObject::~QObject()
销毁对象及其所有子对象。
调用析构时,所有进出该对象的信号都会自动断开连接,事件队列也会删除该对象的所有挂起的发布事件;
删除QObject子类时,使用deleteLater()
通常比delete
更加安全
。
void QObject::deleteLater()
计划删除此对象。
什么是计划删除?
计划删除就是将当前对象标记为稍后删除,也就是在适当时安全删除该对象,其根据事件循环的状态来处理对象的删除,保证程序稳定性和安全性。安全性
deleteLater()可多次安全调用。首次调用后,Qt会处理该对象的删除请求,并自动从事件队列中移除该对象相关的所有待处理事件。
deleteLater()是线程安全的。在多线程环境下,可以安全地从不同线程调用它。工作机制
- 事件循环中的删除:
- 当控制权返回到事件循环时,该对象会被删除。也就是说若程序正在运行一个事件循环(如用户输入、界面更新等)时,对象就会被删除。
- 当事件循环运行前(如在QApplication::exec()之前)调用该函数,对象会在事件循环启动时被删除。
- 当事件循环停止后调用该函数,该对象将不会被删除。
- 当事件循环A中再调用了一个新事件循环A1(如打开模态对话框),不会立即删除对象,而是等到退出A1后并返回到调用该函数的A,才会进行删除。
- 线程中的删除:
当对象在没有在运行事件循环的线程中时,对象会在线程结束时被适时删除(Qt4.8起)。
void QObject::destroyed(QObject *obj = nullptr)
(1)destroyed信号在对象被销毁之前立即发出,所有QPointer实例在这之后都会收到通知,并且该信号不能被阻塞;
- 信号发出时机及作用:在对象即将被销毁时发出,发出该信号后,收到信号的其他对象就得知某个对象即将被销毁,从而去释放资源或更新界面等。
- QPointer:一种智能指针,它会监测所指向的QObject子对象的生命周期。所有指向该对象的QPointer实例,会在destroyed信号发出后被通知,当所指向的对象被销毁时,QPointer会自动将其内部的指针设置为nullptr,无需手动管理指针状态,因而使用Qpointer可以避免悬挂指针问题(dangling pointer)。(2)对象的所有子对象在发出该信号后立即被销毁。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QPointer<MainWindow> w = new MainWindow();
QObject::connect(w, &MainWindow::destroyed, [w](){
// 等待事件循环更新状态
QTimer::singleShot(0, [w](){
qDebug() << "QPointer<MainWindow> is now: " << w; // nullptr
});
});
delete w;
return a.exec();
}
objectName
QString ObjectName;
该属性保存对象的名称。