解读 Q_D, Q_Q 指针

2023-11-11

     见 qglog.h文件定义:   

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

  d指针是在主类中使用的,来获取私有子类成员指针

  q指针是在私有数据类中使用的,来获取主类对象指针

D-指针 
   私有成员总是不可见的,Qt中私有成员不仅仅是简单封装一下,将访问权限改为private,它将所有私有数据封装在私有类里(命名就是 classname##private), 这样一来连用户都不知道他到底封装了什么,程序中只有这个私有类成员指针,这个指针就是D-指针。

从QObject开始看 

 

展开后

 

 

QObject的构造函数如下:   

 

也就是QObjectData *d_ptr = new QObjectPrivate 

显然QObjectPrivate 继承了 QObjectData  ;

如下

 

 

看看QObject的一个方法

 

展开后

 

所以Qt 为我们把从 d_func() 获取 QObjectPrivate 指针的代码给封装起来了,之后就可以直接使用d->

 

 

 

QObject的第二个构造函数使用传入的 QObjectPrivate 对象,但它是 protected 的,也就是说,你不能在外部类中使用这个构造函数。那么这个构造函数有什么用呢?我们来看一下 QWidget 的代码:

 

QWidget 是 QObject 的子类,然后看它的构造函数:

 

 

显然了QWidgetPrivate 继承了QObjectPrivate

于是我们已经明白,为什么 QWidget 中找不到 d_ptr 了,因为所有的 d_ptr 都已经在父类 QObject 中定义好了!尝试展开一下 Q_DECLARE_PRIVATE 宏,你就能够发现,它实际上把父类的 QObjectPrivate 指针偷偷地转换成了 QWidgetPrivate 的指针。

 

因此有如下结论: 

1、在基类中定义一个protected权限的基类私有类d_ptr指针;

2、在每个派生类中用本类私有类初始化d_ptr(该私有类需要继承基类私有类),并定义d_func(),获取基类d_ptr,这个d_func()是由     Q_DECLARE_PRIVATE展开得来的并将其转换为当前私有类指针;


3、在函数中使用Q_D,这样就可以使用d了;
4、在私有数据继承体系中,不要忘记将析构函数定义为虚函数,基类析构函数中释放d_ptr,以防内存泄露!!!

============================================================

Q-指针 
   q指针是在私有数据类中使用的,来获取主类指针。 

class Q_CORE_EXPORT QObjectPrivate : public QObjectData
{
    Q_DECLARE_PUBLIC(QObject)
  public:
   //others...   
    };

展开后:

class Q_CORE_EXPORT QObjectPrivate : public QObjectData
{
    inline QObject* q_func() { return static_cast<QObject *>(q_ptr); } / 
    inline const QObject* q_func() const { return static_cast<const QObject *>(q_ptr); } / 
    friend class QObject; 
   //others
}

  QObjectData定义如下:

QObjectData {
     public:    
    QObject *q_ptr;
    //others    
}
#define Q_Q(QObject) QObject * const q = q_func() 


三、使用的例子:

     在使用调色板中

void QWidget::setPalette(const QPalette &palette)
{
    Q_D(QWidget); //得到私有成员 QWidgetPrivate指针 d
    setAttribute(Qt::WA_SetPalette, palette.resolve() != 0);   
    QPalette naturalPalette = d->naturalWidgetPalette(d->inheritedPaletteResolveMask);
    QPalette resolvedPalette = palette.resolve(naturalPalette);
    d->setPalette_helper(resolvedPalette); //调用QWidgetPrivate::setPalette_helper()
}
void QWidgetPrivate::setPalette_helper(const QPalette &palette)
{
    Q_Q(QWidget);
    if (data.pal == palette && data.pal.resolve() == palette.resolve())
        return;
    data.pal = palette;
    updateSystemBackground();
    propagatePaletteChange();
    updateIsOpaque();
    q->update();  //调用QWidget::update()
    updateIsOpaque();
}





 

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

解读 Q_D, Q_Q 指针 的相关文章

  • Qt 对象的生命周期

    Qt 对象的生命周期是多少 Such as QTcpSocket socket new QTcpSocket 套接字什么时候会被销毁 我应该使用 delete socket 有什么区别吗 QTcpSocket socket 我找不到有关此的
  • 无法初始化静态QList?

    我收到以下错误 Cube cpp 10 error expected initializer before lt lt token 以下是头文件的重要部分 ifndef CUBE H define CUBE H include
  • 如何在点击 Qtablewidget 单元格时获取放置在该单元格中的小部件的行号?

    我正在尝试的是当用户选择项目时获取 QcomboBox 的行号 虽然使用它很容易获得单元格的列和行 cellClicked int int 信号 但仅当单元格上没有小部件时才有效 那么如果单元格中放置了小部件 如何获取行号 Note 所有组
  • QGroupBox边框

    经过一段时间的搜索后 我发现在组框上设置可见边框的方法是使用 StyleSheet 属性 我补充道 border 2px solid gray 但有几个问题 1 组框内的所有内容也继承此设置 2 边框在标题附近有一个小洞 碎片缺失 Here
  • 删除 QComboBox“下拉”动画

    我正在使用 Qt 4 8 并且想在单击 QComboBox 时摆脱 下拉 动画 我也想稍微移动一下 到目前为止 我一直在考虑重新实现 showPopup 和 hidePopup 但不知道如何使其工作 此外 每次我尝试使用 CSS 进行移动或
  • Qt + win32 + mingw 上的原生 Windows API 链接问题

    我正在尝试使用 mingw 工具集将本机 Windows API 与 Qt 结合使用 部分功能存在链接问题 会发生什么 这是 mingw 名称修改的错误吗 ifdef Q WS WIN HWND hwnd QWidget winId HDC
  • QT 应用程序运行时错误?

    我已经在 Windows 7 的 Qt5 1 上开发了一个应用程序 现在我想分发它 由于我使用了 MINGW 编译器 因此无法静态构建它 我使用dependency walker找出所有dll并打包 当我在未安装 QT 开发环境的计算机上运
  • 检查目录是否为空

    我正在尝试检查目录是否为空 MainWindow MainWindow QWidget parent QMainWindow parent ui new Ui MainWindow ui gt setupUi this QDir Dir h
  • QToolBar 的菜单延迟

    我通过制作 QAction 并向其添加 QMenu 在 QToolBar 上有一个菜单 如何消除单击图标时出现菜单之前的延迟 QToolBar myToolBar new QToolBar this QAction myAction new
  • cx_freeze:QODBC 驱动程序未加载

    我的 python 应用程序如下所示 test py from PyQt4 import QtCore from PyQt4 import QtGui from PyQt4 import QtSql import sys import at
  • Windows 消息循环而不是 QApplication::exec() / QApplication::processEvents()

    我是否想念任何一个Qt如果我替换功能QApplication exec 使用标准 Windows 消息循环实现 这应该可以澄清我的意思 运行事件处理的常用 Qt 方式 int main int argc char argv QApplica
  • 调整 QML 图像显示尺寸

    我有一个带有嵌套的 QML 窗口RowLayout 在内排我有两个图像 来源 png这些图像的文件 故意 相当大 当我尝试设置height这些图像上的属性使它们变小 但它们仍然被画得很大 Desired Appearance Actual
  • Qt 支持在 QIcon 中为 SVG 着色

    看来 Qt 不支持 SVG 中路径标签上的描边 填充选项
  • 在 QtCreator 中将 OpenCV 2.3 与 Qt 结合使用

    随着 OpenCV 2 3 版本终于发布 我想在我的系统上编译并安装这个最新版本 由于我经常使用 Qt 和 QtCreator 我当然希望能够在我的 Qt 项目中使用它 我已经尝试了几种方法几个小时 但总是出现错误 第一次尝试 使用WITH
  • 为什么下面的重叠比较总是评估为 true

    我不明白为什么以下代码有警告 指出重叠比较始终评估为真 接下来的语句永远不会被执行 QVariant MainModel data const QModelIndex index int role const if index isVali
  • 如何在 Qt-Embedded 中(正确)输出多语言文本?

    我的目标系统是 linux 3 3 7 Qt Embedded 开源版 4 8 Droid 字体 取自 fonts droid 20111207 git 1 all deb Debian 软件包并复制到 usr lib fonts目录 主要
  • 程序意外完成 - QT Creator

    我正在尝试使用 QT Creator 使用 QT 框架开发 GUI 控制台应用程序 我使用的是Windows XP 我安装了QT 4 8 3和mingw 两者均已安装 没有任何错误 然后我安装了QT Creator QT 版本 路径中的 Q
  • 如何在模型更改时停止ListView“跳跃”

    我需要做什么 我需要创建一个聊天窗口用一个ListView在 QML 中存储聊天消息 我设置listView positionViewAtEnd 以便跟踪最后的消息 我禁用positionViewAtEnd当我向上滚动时 我可以阅读过去的消
  • 禁用 QML Slider 的鼠标滚轮

    我希望能够滚动Flickable使用鼠标滚轮 或触摸板上的两根手指 不改变Sliders它可能包含 示例代码及结果应用 import QtQuick 2 7 import QtQuick Window 2 2 import QtQuick
  • 错误 LNK2001:无法解析的外部符号 __CxxFrameHandler3

    我正在将 Qt 从 VS 2013 迁移到 Qt 5 10 1 到 VS 2015 出现以下多个链接错误 error LNK2001 unresolved external symbol CxxFrameHandler3 error LNK

随机推荐

  • 设计模式------适配器模式

    设计模式 适配器模式 文章目录 设计模式 适配器模式 前言 一 两种形式 二 UML图 对象的适配器模式 类的适配器模式 三 实现要点 四 应用场景 五 优点 六 缺点 七 本质 前言 适配器模式 Adapter Pattern 将一个接口
  • C语言实现两个整数相加

    思路 定义两个变量啊 存放要输入的整数 两个整数相加要存放在一个变量sum 此时可以先定义int sum 0 也可以直接int sum a b 这个意思是a b的值存放在sum 类型是int整型 输出sum即可 我犯的错误 是最后一个pri
  • OpenWrt源码目录

    分析的OpenWrt源码目录有助于分析OpenWrt的源码 一 原始目录 1 1 scripts 构建期间用到的各类脚本文件 它存放了一些脚本 使用了bash python perl等多种脚本语言 编译过程中 用于第三方软件包管理的feed
  • 开关稳压器详解(四)-Buck降压型开关稳压器自举电路

    在Buck开关中 常使用N MOS管作为功率开关管 相比于P MOS N MOS具有导通电阻低价格便宜且流过电流较大等优势 在同步结构中对于开关管的使用一般有两种方式 上管为P MOS 下管为N MOS 无需外部自举电路 上下管均为N MO
  • 建立任务,OSTaskCreate()源码解析

    想让uC OS 管理用户的任务 用户必须要先建立任务 用户可以通过传递任务地址和其它参数到以下两个函数之一来建立任务 OSTaskCreate 或 OSTaskCreateExt OSTaskCreate 与uC OS是向下兼容的 OSTa
  • matlab通过两点画线问题&&plot,line的用法和区别。

    先马 1 LINE并不等同于PLOT 我查过HELP 很多属性不同 2 对与外框的问题 PLOT可以用法BOX控制 LINE无外框 3 图形删除的问题 PLOT可用HOLD ON或OFF控制 LINE要是用DELET 因此建议使用PLOT
  • 尾行3解3D马赛克补丁

    尾行3解3D马赛克补丁 尾行3下载尾行3补丁尾行3图片尾行3去马赛克尾行3怎么玩尾行3下载尾行3视频illusion尾行3秘籍尾行3攻略秘籍 尾行3作弊单机游戏尾行3下载尾行3外挂尾行3对话单机游戏尾行3 尾行3中文补丁 尾行3黑屏补丁尾行
  • M1 Mac 安装Python及相关库|pytorch安装M1 Mac

    今天安装pytorch的时候发现安装的anaconda是x86版本的 自己的电脑是arm64架构的 所以一直安装不上 之后找到一个方法 以后可以通过命令行直接安装在arm64上运行的库了很方便 1 安装homebrew 这是一个mac上的包
  • 编译opencv.js

    opencv 支持编译多个平台 其中还支持JavaScript 不过编译需要emscripten 编译环境 centos7 Python2 7 1 下载OpenCV源码 官网 https opencv org releases 例如下载4
  • Docker如何安装seafile

    SQLite 方式 要在 Docker 中安装 Seafile 您可以按照以下步骤进行操作 安装 Docker 确保您的系统上已经安装了 Docker 您可以根据您的操作系统类型 在官方网站上找到适合您系统的 Docker 版本并进行安装
  • 数字化转型的趋势、挑战与战略【一】

    在全球经济进入数字化转型时期 数字化转型已成为传统企业必须付诸行动的必选题 企业为什么要进行数字化转型 如何把握数字化转型的时机 近日 在大华南IT高管共赢圈 大华南IT培训学院联合举办的 企业数据化转型的战略与规划 培训会上 IDC中国副
  • PyTorch:梯度计算之反向传播函数backward()

    一 计算图 计算图 是一种用来描述计算的有向无环图 我们假设一个计算过程 其中 X 1 mathbf X 1 X1 W 1
  • cmd更换主题配色

    cmd更换主题配色 去github下载colortool 地址 使用管理员打开cmd进入解压后的文件夹 执行命令 colortool exe b solarized light itermcolors 其他可选方案在schemes下 更换效
  • java反射基础巩固

    反射机制是在运行状态中 对于任意一个类 都能够知道这个类的所有属性和方法 对于任意一个对象 都能够调用它的任意一个方法和属性 这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制 一直以来反射技术都是Java中的闪亮点
  • 反射和多线程基础

    一 今日内容 1 1 课程回顾 1 2 反射是啥 1 3 进程和线程 1 4 线程的创建方式 1 5 线程的状态 1 6 线程的常用方法 二 课程回顾 Java的基本语法 1 数据类型 基本 引用 2 运算符 算术 逻辑 比较 赋值 位 三
  • 掌握的几种禁止转换八进制,十进制,十六进制

    1 十进制 除表示正负的符号外 以1 9开头 由0 9组成 如 128 234 278 2 八进制 以0开头 由0 7组成的数 如 0126 050000 3 十六进制 以0X或0x开头 由0 9 A F或a f 组成 如 0x12A 0x
  • 实训周笔记

    主机信息收集技术 基础知识 主要收集目标主机的相关信息 主要包括端口 服务 漏洞等信息 信息收集手段多样 可借助工具也多种多样 端口扫描 Nmap 主机信息收集技术 Nmap namp 192 168 1 1 namp A T4 v 192
  • proteus 问题--解决创建项目、打开项目:Error opening VSM Studio project STM32F401VE,无法查看Source Code,无法创建硬件项目

    问题描述 原因 安装软件的路径有中文 删掉所有东西后 重新下载即可 创建新项目 点击New Project 选择GCC for ARM这个配置项 也可以进入后在配置
  • qt如何触发点击事件_PyQt5事件处理机制(一)

    基于窗体的应用程序都是事件 event 驱动的 鼠标单击 按下某个按键 重绘某个组件 最小化窗口都会产生相应的事件 应用程序对这些事件作出相应的处理以实现程序的功能 常用的特定事件处理函数及方法示例代码 from PyQt5 Qt impo
  • 解读 Q_D, Q_Q 指针

    见 qglog h文件定义 define Q D Class Class Private const d d func define Q Q Class Class const q q func d指针是在主类中使用的 来获取私有子类成员指