0.QObject的数据存储
一、QObject概述
QObject类是QT的核心,大部分QT类都是从这个类直接或者间接继承而来。包含QT的信号槽机制和事件机制
QObject通过对象树将对象组织起来,当使用QObject创建一个对象作为其他对象的父对象时,QObject对象会将其他对象自动添加到子对象的列表中,注意,这里的对象数和父子对象关系不是C++里面的父类和子类的关系,只是一种单纯的树型组织结构
二、QObject的数据存储
QObject 类的相关文件一共有四个:
qobject.h,QObject class定义的头文件
qobject.cpp,QObject class 和QMetaObject class的实现文件,实现了signal、slot、properties等核心部分
qobjectdefs.h,定义了 QMetaObject class。
qobject_p.h,定义了 QObjectPrivate 类,用来存储 QOjbect 对象的成员数据。
先看下qobject.h
class Q_CORE_EXPORT QObject
{Q_DECLARE_PRIVATE(QObject)
public:Q_INVOKABLE explicit QObject(QObject *parent=nullptr);virtual ~QObject();//......
protected:QObject(QObjectPrivate &dd, QObject *parent = nullptr);QScopedPointer<QObjectData> d_ptr;
};class Q_CORE_EXPORT QObjectData {Q_DISABLE_COPY(QObjectData)
public:QObjectData() = default;virtual ~QObjectData() = 0;//......
};
Q_DISABLE_COPY在qglobal.h中,实现如下
#define Q_DISABLE_COPY(Class) \Class(const Class &) = delete;\Class &operator=(const Class &) = delete;
主要是为了防止QObjectData被拷贝和赋值
qobject.h中,定义了QObject和QObjectData两个类,QObjectData用来存储QObject的数据,并且在QObject被定义为智能指针d_ptr,QScopedPointer保证当指向对象离开作用域后,指向的对象将被删除。防止内存泄露
Q_DECLARE_PRIVATE在qglobal.h中,实现如下
#define Q_DECLARE_PRIVATE(Class) \inline Class##Private* d_func() \{ Q_CAST_IGNORE_ALIGN(return reinterpret_cast<Class##Private *>(qGetPtrHelper(d_ptr));) } \inline const Class##Private* d_func() const \{ Q_CAST_IGNORE_ALIGN(return reinterpret_cast<const Class##Private *>(qGetPtrHelper(d_ptr));) } \friend class Class##Private;
Class##Private中的##的作用是连接,当传入QObject后,Class##Private就变成QObjectPrivate
所以,Q_DECLARE_PRIVATE(QObject)展开后代码如下:
#define Q_DECLARE_PRIVATE(Class) \inline QObjectPrivate* d_func() \{ Q_CAST_IGNORE_ALIGN(return reinterpret_cast<QObjectPrivate *>(qGetPtrHelper(d_ptr));) } \inline const QObjectPrivate* d_func() const \{ Q_CAST_IGNORE_ALIGN(return reinterpret_cast<const QObjectPrivate *>(qGetPtrHelper(d_ptr));) } \friend class QObjectPrivate;
其中的qGetPtrHelper是个模板函数
template <typename T> inline T *qGetPtrHelper(T *ptr) { return ptr; }
template <typename Ptr> inline auto qGetPtrHelper(Ptr &ptr) -> decltype(ptr.operator->()) { return ptr.operator->(); }
所以,如果class是QObject,d_func的作用就是将QObject对象的指针转化为QObjectPrivate的指针
而QObjectPrivate在qobject_p.h中定义
class Q_CORE_EXPORT QObjectPrivate : public QObjectData
{Q_DECLARE_PUBLIC(QObject)QObjectPrivate(int version = QObjectPrivateVersion);virtual ~QObjectPrivate();//下面是signal 和slot 的数据,属性数据等
};
QObjectPrivate继承了QObjectData,由于QObjectData是个纯虚类,所以具体的实现在QObjectPrivate中
而在QObject的构造函数中,将QObjectData的指针d_ptr初始化为QObjectPrivate
QObject::QObject(QObject *parent): d_ptr(new QObjectPrivate)
{//......
}QObject::QObject(QObjectPrivate &dd, QObject *parent): d_ptr(&dd)
{//......
}
以具体的QWidget为例,QWidget的定义如下,在qwidget.h的头文件中
class Q_WIDGETS_EXPORT QWidget : public QObject, public QPaintDevice
{Q_OBJECTQ_DECLARE_PRIVATE(QWidget)explicit QWidget(QWidget* parent = nullptr, Qt::WindowFlags f = Qt::WindowFlags());//private构造,防止对QWidget进行拷贝和赋值~QWidget();//......
};
QWidget公有继承了QObject
QWidget构造函数的具体实现如下:
QWidget::QWidget(QWidget *parent, Qt::WindowFlags f): QObject(*new QWidgetPrivate, 0), QPaintDevice()
{QT_TRY {d_func()->init(parent, f);} QT_CATCH(...) {QWidgetExceptionCleaner::cleanup(this, d_func());QT_RETHROW;}
}/*! \internal*/
QWidget::QWidget(QWidgetPrivate &dd, QWidget* parent, Qt::WindowFlags f): QObject(dd, 0), QPaintDevice()
{Q_D(QWidget);QT_TRY {d->init(parent, f);} QT_CATCH(...) {QWidgetExceptionCleaner::cleanup(this, d_func());QT_RETHROW;}
}
这两个构造函数都调用了基类QObject的对应的构造函数,并以QWidgetPrivate的对象和指针作为第一个参数传进去。然后调用init函数,d_func()返回的是d_ptr,是QObjectPrivate的指针,而QObjectPrivate是QWidgetPrivate的基类,代码如下
class Q_WIDGETS_EXPORT QWidgetPrivate : public QObjectPrivate
{Q_DECLARE_PUBLIC(QWidget)
public:explicit QWidgetPrivate(int version = QObjectPrivateVersion);~QWidgetPrivate();
};
所以,基类(QObject)中的d_ptr指针将会指向一个QWidgetPrivate类型的对象,dd将和QWidgetPrivate对象绑定,从而最终调用QWidgetPrivate中的init函数。
所以,通过上述的分析可知,在QT中,QObject类和数据分别是通过两个类QObject和QObjectData来封装的,然后QObjectPrivate又继承了QObjectData,实现了QObjectData中的一部分功能
当要创建一个具体的QT对象时,比如QWidget,会先调用父类QObject构造函数,然后通过C++的多态机制将QWidget的数据部分QWidgetPrivate传入父类QObject的构造函数,从而使对象父类QObject中的数据指针:d_ptr(QObjectPrivate类型的)指向对象的数据QWidgetPrivate,然后就可以使用或操作具体对象的数据了
将类和类的数据分别封装在两个类中,使得类本身和类数据的封装性更好,降低了类数据和类本身之间的耦合
参考
Inside Qt Series
欢迎大家评论交流,作者水平有限,如有错误,欢迎指出
0.QObject的数据存储相关推荐
- Python爬取数据存储到本地文本文件
前面说过Python爬取的数据可以存储到文件.关系型数据库.非关系型数据库.前面两篇文章没看的,可快速戳这里查看!https://mp.weixin.qq.com/s/A-qry4r3ymuCLXLB ...
- Matchvs多种数据存储接口对比分析
Matchvs 给开发者提供了三种存储接口:用户数据存储.全局数据存储.哈希存储. 三种数据存储的特点及对比如下: 用户数据存储,存储用户数据,只有用户自己有增.删.改.查自己数据的权限 全局数据存储 ...
- 基于Python操作将数据存储到本地文件
点击蓝字 关注我们 前面说过Python爬取的数据可以存储到文件.关系型数据库.非关系型数据库.前面两篇文章没看的,可快速戳这里查看!<使用Python将数据存入SQLite3数据库> & ...
- AS3.0编程 So本地数据存储(“超级cookies”)--AS3:Local SharedObject
Flash影片运行过程中,大多数的数据都存储于影片本身,一旦影片被关闭,这些数据也就从内存中被清除掉,下次运行时,数据将从头开始.若想存储数据或者让客户端的多个影片共享同一组数据,就要想办法把数据存储 ...
- [转]ActionScript 3.0入门:Hello World、文件读写、数据存储(SharedObject)、与JS互调
本文转自:http://www.cnblogs.com/artwl/p/3396330.html 近期项目中可能要用到Flash存取数据,并与JS互调,所以就看了一下ActionScript 3.0, ...
- Android数据存储之GreenDao 3.0 详解
前言: 今天一大早收到GreenDao 3.0 正式发布的消息,自从2014年接触GreenDao至今,项目中一直使用GreenDao框架处理数据库操作,本人使用数据库路线 Sqlite----> ...
- ActionScript 3.0入门:Hello World、文件读写、数据存储(SharedObject)、与JS互调
近期项目中可能要用到Flash存取数据,并与JS互调,所以就看了一下ActionScript 3.0,现把学习结果分享一下,希望对新手有帮助. 目录 ActionScript 3.0简介 Hello ...
- 从0到1搭建大数据平台之数据存储
大家好,我是脚丫先生 (o^^o) 近日参加了集团大数据平台之流批一体的建设. 流批一体,从调研直至研发.日日夜夜,泪流满面. 作业以:sql.jar.组件拖拽三种方式去提交实时任务,终究还是攻克. ...
- [VPX611]基于 6U VPX 总线架构的SATA3.0 高性能数据存储板
板卡概述 VPX611 是一款基于6UVPX 总线架构的高性能数据存储板,该板卡采用2 片XilinxKintex-7 系列FPGA 作为主控单元,FPGA 内嵌RAID 控制器,最大支持8 个mSA ...
最新文章
- mac下git与github简单使用
- JAVA是如何传递参数的?是传值(by value)?还是传地址(by reference)?
- SQL中left join、right join、inner join的区别
- 4位快速加法器和4位串行加法器相比_使用混合信号示波器调试串行总线系统
- Exchange Server 2016管理系列课件50.DAG管理之激活数据库副本
- (计算机组成原理)第五章中央处理器-第四节2:微程序控制器基本原理
- Elasticsearch aggregations API
- 程序员风光背后:从零到BAT数据分析师靠的是什么?
- 图片尺寸判断等-我们到底能走多远系列(21)
- sap系统ftp服务器下文件,sap ftp服务器
- 来给你的CSDN博客换个皮肤~
- win10下使用mklink命令给C盘软件搬家
- pixel 2 xl的root之旅
- 国外android大神博客,Android手机浏览器(国外篇)横向对比评测
- C# 文件搜索过程中如何提取office文件,wps,pdf,html,eml等格式的文件正文
- 目标跟踪 OP,CLE,DP,AUC的概念和计算
- 面试关于网络的那些事
- 百度地图自定义吹出框
- 小程序源码:百变头像框制作微信小程序源码下载,免服务器和域名
- Vscode extensions开发