QT(5)—— Q_D 与 Q_Q QObject与 QObjectPrivate

2023-11-01

核心就是

QObject::QObject(QObjectPrivate &dd, QObject *parent)
    : d_ptr(&dd)
{
    d_ptr->q_ptr = this;   //互指
}
template <typename T> static inline T *qGetPtrHelper(T *ptr) { return ptr; }
template <typename Wrapper> static inline typename Wrapper::pointer qGetPtrHelper(const Wrapper &p) { return p.data(); }

#define Q_DECLARE_PRIVATE(Class) \
    inline Class##Private* d_func() { return reinterpret_cast<Class##Private *>(qGetPtrHelper(d_ptr)); } \
    inline const Class##Private* d_func() const { return reinterpret_cast<const Class##Private *>(qGetPtrHelper(d_ptr)); } \
    friend class Class##Private;

#define Q_DECLARE_PRIVATE_D(Dptr, Class) \
    inline Class##Private* d_func() { return reinterpret_cast<Class##Private *>(Dptr); } \
    inline const Class##Private* d_func() const { return reinterpret_cast<const Class##Private *>(Dptr); } \
    friend class Class##Private;

#define Q_DECLARE_PUBLIC(Class)                                    \
    inline Class* q_func() { return static_cast<Class *>(q_ptr); } \
    inline const Class* q_func() const { return static_cast<const Class *>(q_ptr); } \
    friend class Class;

#define Q_D(Class) Class##Private * const d = d_func()
#define Q_Q(Class) Class * const q = q_func()

  1. private 是指类的私有类Class##Private ,这个是使得类成为QT的类的实现
  2. q_func可以从q_ptr指针强制获得类的指针
  3. d_func可以从d_ptr指针强制获得类额私有类的指针
  4. q_func和d_func都有两个同名函数属于重载 ,const
  5. public 指类本身

涉及到类中的两个指针d_ptr 和q_ptr

看一下两个的定义

QObjectData *d_ptr 的定义

class Q_CORE_EXPORT QObject
{
	Q_INVOKABLE explicit QObject(QObject *parent=0);
protected:
    QObject(QObjectPrivate &dd, QObject *parent = 0);
    
    QScopedPointer<QObjectData> d_ptr;

}

QObjectData

中QObject *q_ptr 的定义

class Q_CORE_EXPORT QObjectData {
public:
    virtual ~QObjectData() = 0;
    QObject *q_ptr;
    QObject *parent;
    QObjectList children;

    uint isWidget : 1;
    uint blockSig : 1;
    uint wasDeleted : 1;
    uint isDeletingChildren : 1;
    uint sendChildEvents : 1;
    uint receiveChildEvents : 1;
    uint isWindow : 1; //for QWindow
    uint unused : 25;
    int postedEvents;
    QDynamicMetaObjectData *metaObject;
    QMetaObject *dynamicMetaObject() const;
};

d_ptr的初始化

Q_INVOKABLE explicit QObject(QObject *parent=0);

QObject::QObject(QObject *parent)
    : d_ptr(new QObjectPrivate)
{
    Q_D(QObject);
    d_ptr->q_ptr = this;
    d->threadData = (parent && !parent->thread()) ? parent->d_func()->threadData : QThreadData::current();   
}
QObject::QObject(QObjectPrivate &dd, QObject *parent)
    : d_ptr(&dd)
{
    Q_D(QObject);
    d_ptr->q_ptr = this;
    d->threadData = (parent && !parent->thread()) ? parent->d_func()->threadData : QThreadData::current();

看一下QObjectPrivate的类型定义

#define Q_DECLARE_PUBLIC(Class)                                    \
    inline Class* q_func() { return static_cast<Class *>(q_ptr); } \
    inline const Class* q_func() const { return static_cast<const Class *>(q_ptr); } \
    friend class Class;

#define Q_Q(Class) Class * const q = q_func()

class Q_CORE_EXPORT QObjectPrivate : public QObjectData
{
    Q_DECLARE_PUBLIC(QObject)
}

继承自QObjectData,同时通过宏扩展出一个函数q_func ,再通过Q_Q 扩展出一个类类型的指针变量q,以供获取到该私有数据类对应的类型的对象指针。

用QObjectPrivate进行赋值,QObjectPrivate是一个继承QObjectData的类型,通用的定义形式是classNamePrivate,表明是一个继承QObject的类中的私有数据,在整个继承体系中,所有类的私有数据的初始化赋值都到达了Qobject 中定义的QScopedPointer d_ptr,由其进行保存。

QT中私有数据类型的定义一般在XXX_P.h中定义,如qcoreapplication_p.h;但是实现却是和类型一起在同一个.c文件中,例如qcoreapplication.cpp。

然后通过Q_D进行类型的强制转换变为子类所持有的私有数据类型,因为QObjectData也是被各个私有数据类型进行继承和扩展的。

Q_Q的作用就是,将QObejctData中存储的QObject *q_ptr,转换成子类的类型,参数是子类的类型名,经过宏 成为类型,强制转换类型。

d_ptr和q_ptr的就是一对相互持有彼此指针的数据,从q_ptr指向的类型的可以获取到d_ptr的私有数据,通过d_ptr的私有数据类型可以获取到包含d_ptr的类型的类对象指针。

q_ptr的初始化;

QObject::QObject(QObject *parent)
    : d_ptr(new QObjectPrivate)
{
    Q_D(QObject);
    d_ptr->q_ptr = this;
}

例子 ,QWidget

class Q_WIDGETS_EXPORT QWidget : public QObject, public QPaintDevice
{
    Q_OBJECT
    Q_DECLARE_PRIVATE(QWidget)
    
    explicit QWidget(QWidget* parent = 0, Qt::WindowFlags f = 0);
}

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;
    }
}

QObject(*new QWidgetPrivate, 0) 使得第一个参数值被赋值到d_ptr,同时QObject 的构造函数中,将d_ptr的中保有的q_ptr赋值为this,即当前类型实例对象的指针。

也可以直接通过传入私有数据类型的引用进行构造,如下。

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;
    }
}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

QT(5)—— Q_D 与 Q_Q QObject与 QObjectPrivate 的相关文章

  • Linux 上的静态 Qt5 构建:部署时如何处理字体?

    我使用这些配置选项创建了 Qt 5 2 0 库的静态版本 Ubuntu 12 04 开源 确认许可 force pkg config 发布 静止的 前缀 home juzzlin qt5 无icu opengl桌面 无油嘴滑舌 辅助功能 n
  • 如何将 QFile 与 std::iostream 一起使用?

    是否可以像 std iostream 一样使用 QFile 我很确定那里一定有一个包装纸 问题是在哪里 我有另一个库 它需要 std istream 作为输入参数 但在我的程序中 此时我只有一个 QFile 我使用以下代码提出了自己的解决方
  • 是否可以根据 QSlider 的位置来改变其手柄的颜色?

    我非常清楚如何通过样式表自定义 QSlider 但我想知道是否可以执行以下操作 我希望滑块的手柄从蓝色变为黄色 当设置在左侧时 它是蓝色的 设置在左侧时 它是蓝色的 当你将它向右移动时 它会出现从蓝色到黄色的渐变 如果可以通过样式表 如何实
  • Qt 相当于 .NET 数据绑定吗?

    Qt 中是否有相当于 NET 数据绑定的功能 我想使用引用数据库中特定实体的 QString 填充一些组合框和其他小部件 但是 如果我可以将数据绑定到这些字符串 而不是基于新的组合框选择再次查询数据库 或者基于构建我自己的将使用 QStri
  • CMake AUTOMOC,文件位于不同文件夹中

    我有一个简单的 CMake 项目 proj project folder a h a cpp CMakeLists txt CMakeLists txt cmake minimum required VERSION 3 2 set CMAK
  • QByteArray 到整数

    正如您可能从标题中看出的那样 我在转换QByteArray为一个整数 QByteArray buffer server gt read 8192 QByteArray q size buffer mid 0 2 int size q siz
  • 一个具有完全透明背景的qt小部件

    我需要创建一个 qt 小部件 它将充当其他一些小部件的父级 并对它们进行排序 现在的问题是如何使其背景完全透明 我想这样做 struct Imp Imp QWidget parent thisWidget new QWidget paren
  • Qt 5.3 QPlainTextEdit 更改 QTextCursor 颜色

    我想更改下面的光标颜色QPlainTextEdit小部件 我能够将其宽度设置为6 但我想改变颜色或者它 是否可以 QFontMetrics fm font setCursorWidth fm averageCharWidth setCurs
  • PyQt5 使动态小部件可点击并将参数传递给另一个函数

    我正在尝试制作动态小部件并使它们可点击 通过单击一个小部件 它应该将动态值传递给其他小部件 我尝试过 sender 和其他访问小部件的选项 但没有任何效果 所有小部件都从最后一个小部件发送信息 下面是代码 import sys from P
  • Qt - ubuntu中的串口名称

    我在 Ubuntu 上查找串行端口名称时遇到问题 如您所知 为了在 Windows 上读取串口 我们可以使用以下代码 serial gt setPortName com3 但是当我在 Ubuntu 上编译这段代码时 我无法使用这段代码 se
  • QML 圆规

    我目前正在创建一个虚拟仪表板 我想获得针后面的进度条类型 如以下链接所示 https forum qt io topic 89307 qml circular gauge styling needle trailing colour glo
  • Android 上与 Qt 5.2 的蓝牙通信[关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我想使用 Qt 框架使我的 Android 设备能够通过蓝牙进行通信 截至今天 Qt 5 2 是最新的 据我所知 尚不支持蓝牙 在本页
  • 通过信号/槽将 QVector 从工作线程传递到主线程

    目前 我在将 QVector 传递到线程之间时遇到一些麻烦 目前我有一个主线程 GUI Thread 和一个频繁发出 QVector 数组的工作线程 在向量内直接发出数据之前看起来不错 接收者是主线程中的一个槽 但该槽接收到的数据是乱码 这
  • 从 QWebEngineView 或 QWebEnginePage 中删除滚动条

    有没有办法删除滚动条QWebEngineView或者我可以以某种方式访问 它的 ScrollArea 吗 使用 webkit 就这么简单 WebView gt page gt setScrollBarPolicy Qt Vertical Q
  • 使用 CMake 时出现 Qt moc 错误

    我正在尝试编写一个 OpenCV 应用程序 使用 Qt 创建 GUI 并使用 CMake 生成 makefile 我遇到的问题是 当我尝试执行make命令 我收到错误 该文件是使用 5 2 1 中的 moc 生成的 它不能与此版本的 Qt
  • 如何在 Qt4 OpenGL 应用程序中启用 HiDPI (Retina) 支持?

    我正在使用带有 QGraphicsView 的 QGraphicsScene 如中所述这个文件 https doc qt io archives qq qq26 openglcanvas html 我打算最终将 Qt 小部件覆盖在我的 Op
  • Qt - 如何在保留选中状态的同时禁用 QCheckBox?

    我有一个带有两个复选框的对话框 我们称它们为 A 和 B 当未选中 A 时 B 应该能够根据用户的需要进行切换 当 A 被选中时 B 不应该能够被切换 现在 我的对话框构造函数中有以下内容 connect ui gt A SIGNAL to
  • QTextEdit:仅当滚动条位于底部时自动向下滚动

    有一个 QTextEdit 显示相当多的文本 它不可编辑 假设我想在开头阅读一些内容 向上滚动 但随后添加了一个新行 并且滚动条自动转到底部 我在使用各种程序时遇到类似的问题 无论它们是用什么语言编写的 如何处理这个问题 当向文本添加新行时
  • Qt 模型/视图与标准小部件

    我目前正在阅读模型 视图tutorial http qt project org doc qt 4 8 modelview html来自 Qt 但我仍然不确定是否应该为我的 Qt 程序使用模型 视图或小部件 我需要做一个记录器应用程序来监视
  • 如何在 Blackberry Cascades 中显示具有特定号码的电话板

    我正在使用带有 C QT 和 QML 的 Blackberry Cascades 10 Beta 3 SDK 以及 Blackberry 10 Dev Alpha Simulator 和 QNX Momentics IDE 并且我正在尝试实

随机推荐

  • spring JDBCTemplate 批量插入 返回id 批量插入返回批量id

    http www iteye com topic 1135650 1 插入一条记录返回刚插入记录的id Java代码 public int addBean final Bean b final String strSql insert in
  • 红黑树和AVL树的比较分析

    定义 AVL树全称是平衡二叉搜索树 相比于红黑树 他是一种高度平衡的二叉搜索树 所有节点的左右子树高度差不超过1 红黑树是一种弱平衡的二叉搜索树 它只要求部分达到平衡 其保证最长路径最多是最短路径的2倍 增删查比较 插入 就插入节点导致树失
  • 团队管理和协作,Markdown,原型的使用

    背景 公司的技术文档和接口都需要多人合作编写 博客只能是个人的技术总结 无法有效的团队管理 最终 技术文档 接口 数据字典 查看Demo web页面原型 app原型 在线作图 流程图 思维导图 原型图 UML 网络拓扑图 组织结构图
  • 【信息】宁波银行金融科技部:常见问题解答

    0 内推 我的内推码 90OF50 宁波银行金融科技部2023届校招开始了 内推码 90OF50 社招请直接与我联系哦 1 说明 本文是对很多朋友都关心的一些问题的集中解答 以免大家重复地询问一样的问题 大家自取自己关注的内容即可 顺序可能
  • Android Studio制作简单计算器

    代码地址 https github com xjhqre android calculator 效果演示 1 连续加法 2 连续减法 3 连续乘法 4 连续除法 5 优先级运算 6 退格功能 7 错误提示 制作步骤 1 创建按钮图片 1 1
  • bat小游戏代码大全_Python俄罗斯方块游戏代码

    本游戏共两个文件 blocks py和main py blocks py定义各类方块 main py定义游戏画面 blocks py import randomfrom collections import namedtuplePoint
  • CSS导航栏及下拉菜单

    导航栏对于一个网站来说非常重要 熟练地使用CSS可以转换成好看的导航栏而不是枯燥的HTML菜单 导航栏基本上是一个链接列表 所以使用 ul ul 和 li li 元素非常有意义 导航栏就是建立在列表标签的精确熟练使用上 小复习 伪类的使用方
  • SQL的开窗函数

    引用 在开窗函数出现之前存在着非常多用 SQL 语句非常难解决的问题 非常多都要通过复杂的相关子查询或者存储过程来完毕 为了解决这些问题 在2003年ISO SQL标准增加了开窗函数 开窗函数的使用使得这些经典的难题能够被轻松的解决 眼下在
  • 怎么查看端口号被哪个程序占用从而解决端口冲突

    在java后台开发过程中我们可能都会遇到端口被占用的问题 但是此时又不知道端口被哪个端口占用 用下面方法可以查看端口是被哪个程序占用 然后结束这个程序就可以解决端口被占用的问题 1 按windows R键 输入cmd命令 回车 2 输入ne
  • 【微信小程序开发】一文带你详解小程序组件和 API 的使用

    引言 在小程序开发中 组件和API是非常重要的部分 它们可以帮助我们构建丰富的用户界面和实现各种功能 本文将介绍小程序中常用的组件和API 并提供相应的代码示例 文章目录 引言 组件 文本组件 图片组件 按钮组件 输入框组件 列表组件 AP
  • 三大移动Web开发框架哪个适合你?

    我最近特别关注JavaScript驱动的移动应用开发解决方案 先后撰文介绍了众多的相关话题 包括jQuery Mobile jQTouch Sencha Touch和PhoneGap 我得承认 要搞清楚这一批前沿技术并非易事 于是我这回概述
  • java远程调试_Java 远程调试原理(学习笔记)

    Java远程调试的原理 JDWP Java Debug Wire Protocol 两个VM之间通过debug协议进行通信 然后以达到远程调试的目的 两者之间可以通过socket进行通信 其中 调试的程序常常被称为debugger 而被调试
  • postgis中将数据库备份到其它数据库中还原

    1 备份数据库 可以用命令操作 pg dump U postgres h hostip d joint boot Fc gt D python Project PG data joint jar 2 创建新的数据库 可以在其它postgis
  • vCard和MECARD格式

    vcard和MECARD都是电子名片的格式 这几篇文章介绍都很详细 MECARD格式的电子名片简单介绍 链接1 链接2 vCard格式 链接 分割线 补充一个只有微信扫码时会出现的问题 不管是vCard还是MECARD 也不管vCard是2
  • SpringBoot优缺点分析

    Spring的优点分析 Spring是Java企业版 Java Enterprise Edition JEE 也称J2EE 的轻量级代替品 无需开发重量级的Enterprise JavaBean EJB Spring为企业级Java开发提供
  • java进阶一:java集合

    1 集合简介 集合和数组类似 都是储存元素的容器 数组像是静态容器 长度一旦创建就不能再改变 元素类型必须统一 只能通过下标去索引元素等 集合像是动态容器 集合的长度可以动态的改变 元素类型可以不一致 可以用某个映射的关系去索引元素等 ja
  • vue-admin-template学习(一)

    vue admin template学习 一 vue admin template 框架结构 克隆运行项目 vue admin template项目改造 一 分析登录请求的思路 请求路线 登录 创建axios实例 request拦截器 re
  • Java实现捕鱼达人附源码

    1 游戏原理 swing 多线程 事件监听 swing实现的界面的绘制 多线程实现产生多种鱼 实现鱼的游动 以及网的移动 事件监听实现鼠标捕鱼事件的捕获 2 主要类和方法解释 鱼 背景 网都是图片 之所有是动态的效果 因为线程或者鼠标移动引
  • 批量替换文件及文件夹名称(bat)

    echo off SetLocal EnableDelayedExpansion set p old 输入原字符 Set p new 输入新字符 先处理文件 For f delims i in dir s b a d do Set a nx
  • QT(5)—— Q_D 与 Q_Q QObject与 QObjectPrivate

    核心就是 QObject QObject QObjectPrivate dd QObject parent d ptr dd d ptr gt q ptr this 互指 template