Q_DECLARE_PRIVATE与Q_DECLARE_PUBLIC

2023-11-10

Q_DECLARE_PRIVATE与Q_DECLARE_PUBLIC

这两个宏在Qt的源码中随处可见,重要性不言而喻。在 部落格的 Inside Qt Series 系列文章中,他用了3篇文章来讲这个问题。

因为 QObject 本身比较复杂,这两个宏和一个复杂的东西搅和到一块,还真是不好理解。不过幸好,这个两个宏和QObject 没有必然的联系。故接下来,忘记 QObject,看一个普通的C++的类

例子

类 QtServiceController 定义:

class QtServiceController 
{
   Q_DECLARE_PRIVATE(QtServiceController) 
 public:
 QtServiceController(const QString &name);
 //省略其他 
private:
 QtServiceControllerPrivate *d_ptr; 
};

宏定义

宏定义在 QtGlobal(即qglobal.h)头文件中:

#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_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;

这两个宏在这看起来真蛮绕的,因为这个例子太简单了,两个宏的威力发挥不出来。反正核心就是:

  • 在 QtServiceController 中通过 d_func() 可以获得 QtServiceControllerPrivate 的指针 d_ptr

  • 在 QtServiceControllerPrivate 中通过 q_func() 可以获得 QtServiceController 的指针 q_ptr

Q_D 与 Q_Q

这是另两个Qt源码中随处可见的宏,那么它们有什么用呢?

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

两个宏展开后分别是对 d_func 和 q_func 两个函数的调用,返回值分别赋值给 d 和 q 两个指针变量。

于是:

  • 在 QtServiceController 中的成员函数中,我们只需要添加 Q_D(QtServiceController) 宏,在该函数内就可以直接用 d 来指代 d_ptr

  • 在 QtServiceControllerPrivate 中的成员函数中,我们只需要添加 Q_Q(QtServiceController)宏,在该函数内就可以直接用 q 来指代 q_ptr

d_ptr与q_ptr

绕这么大圈,为什么不直接用 d_ptr 与 q_ptr 呢。在,在我们的例子中,确实可以直接用,而且会更直接更简单。官方这么用了,或许是为了和其他类保持一致吧。

但在其他情况下,这么做显然是有意义的,因为 d_ptr 与 d,q_ptr 与 q 的类型并不一致(比如QObject系列)。这也是为何宏展开后有cast的原因























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

Q_DECLARE_PRIVATE与Q_DECLARE_PUBLIC 的相关文章

  • “构建”构建我的项目,“构建解决方案”则不构建

    我刚刚开始使用VS2010 我有一个较大的解决方案 已从 VS2008 成功迁移 我已将一个名为 Test 的控制台应用程序项目添加到解决方案中 选择构建 gt 构建解决方案不编译新项目 选择构建 gt 构建测试确实构建了项目 在失败的情况
  • 查找c中结构元素的偏移量

    struct a struct b int i float j x struct c int k float l y z 谁能解释一下如何找到偏移量int k这样我们就可以找到地址int i Use offsetof 找到从开始处的偏移量z
  • 使用实体框架模型输入安全密钥

    这是我今天的完美想法 Entity Framework 中的强类型 ID 动机 比较 ModelTypeA ID 和 ModelTypeB ID 总是 至少几乎 错误 为什么编译时不处理它 如果您使用每个请求示例 DbContext 那么很
  • 从Web API同步调用外部api

    我需要从我的 Web API 2 控制器调用外部 api 类似于此处的要求 使用 HttpClient 从 Web API 操作调用外部 HTTP 服务 https stackoverflow com questions 13222998
  • HTTPWebResponse 响应字符串被截断

    应用程序正在与 REST 服务通信 Fiddler 显示作为 Apps 响应传入的完整良好 XML 响应 该应用程序位于法属波利尼西亚 在新西兰也有一个相同的副本 因此主要嫌疑人似乎在编码 但我们已经检查过 但空手而归 查看流读取器的输出字
  • 关于 C++ 转换:参数 1 从“[some_class]”到“[some_class]&”没有已知的转换

    我正在研究 C 并且遇到了一个错误 我不知道确切的原因 我已经找到了解决方案 但仍然想知道原因 class Base public void something Base b int main Base b b something Base
  • 带动态元素的 WPF 启动屏幕。如何?

    我是 WPF 新手 我需要一些帮助 我有一个加载缓慢的 WPF 应用程序 因此我显示启动屏幕作为权宜之计 但是 我希望能够在每次运行时更改屏幕 并在文本区域中显示不同的引言 这是一个生产力应用程序 所以我将使用非愚蠢但激励性的引言 当然 如
  • 显示UnityWebRequest的进度

    我正在尝试使用下载 assetbundle统一网络请求 https docs unity3d com ScriptReference Networking UnityWebRequest GetAssetBundle html并显示进度 根
  • 如何设计以 char* 指针作为类成员变量的类?

    首先我想介绍一下我的情况 我写了一些类 将 char 指针作为私有类成员 而且这个项目有 GUI 所以当单击按钮时 某些函数可能会执行多次 这些类是设计的单班在项目中 但是其中的某些函数可以执行多次 然后我发现我的项目存在内存泄漏 所以我想
  • 如何在整个 ASP .NET MVC 应用程序中需要授权

    我创建的应用程序中 除了启用登录的操作之外的每个操作都应该超出未登录用户的限制 我应该添加 Authorize 每个班级标题前的注释 像这儿 namespace WebApplication2 Controllers Authorize p
  • 如何在 C 中调用采用匿名结构的函数?

    如何在 C 中调用采用匿名结构的函数 比如这个函数 void func struct int x p printf i n p x 当提供原型的函数声明在范围内时 调用该函数的参数必须具有与原型中声明的类型兼容的类型 其中 兼容 具有标准定
  • 如何查看网络连接状态是否发生变化?

    我正在编写一个应用程序 用于检查计算机是否连接到某个特定网络 并为我们的用户带来一些魔力 该应用程序将在后台运行并执行检查是否用户请求 托盘中的菜单 我还希望应用程序能够自动检查用户是否从有线更改为无线 或者断开连接并连接到新网络 并执行魔
  • 如何使用 C# / .Net 将文件列表从 AWS S3 下载到我的设备?

    我希望下载存储在 S3 中的多个图像 但目前如果我只能下载一个就足够了 我有对象路径的信息 当我运行以下代码时 出现此错误 遇到错误 消息 读取对象时 访问被拒绝 我首先做一个亚马逊S3客户端基于我的密钥和访问配置的对象连接到服务器 然后创
  • 向现有 TCP 和 UDP 代码添加 SSL 支持?

    这是我的问题 现在我有一个 Linux 服务器应用程序 使用 C gcc 编写 它与 Windows C 客户端应用程序 Visual Studio 9 Qt 4 5 进行通信 是什么very在不完全破坏现有协议的情况下向双方添加 SSL
  • 通过指向其基址的指针删除 POD 对象是否安全?

    事实上 我正在考虑那些微不足道的可破坏物体 而不仅仅是POD http en wikipedia org wiki Plain old data structure 我不确定 POD 是否可以有基类 当我读到这个解释时is triviall
  • C# 成员变量继承

    我对 C 有点陌生 但我在编程方面有相当广泛的背景 我想做的事情 为游戏定义不同的 MapTiles 我已经像这样定义了 MapTile 基类 public class MapTile public Texture2D texture pu
  • 基于 OpenCV 边缘的物体检测 C++

    我有一个应用程序 我必须检测场景中某些项目的存在 这些项目可以旋转并稍微缩放 更大或更小 我尝试过使用关键点检测器 但它们不够快且不够准确 因此 我决定首先使用 Canny 或更快的边缘检测算法 检测模板和搜索区域中的边缘 然后匹配边缘以查
  • 哪种 C 数据类型可以表示 40 位二进制数?

    我需要表示一个40位的二进制数 应该使用哪种 C 数据类型来处理这个问题 如果您使用的是 C99 或 C11 兼容编译器 则使用int least64 t以获得最大的兼容性 或者 如果您想要无符号类型 uint least64 t 这些都定
  • 如何将服务器服务连接到 Dynamics Online

    我正在修改内部管理应用程序以连接到我们的在线托管 Dynamics 2016 实例 根据一些在线教程 我一直在使用OrganizationServiceProxy out of Microsoft Xrm Sdk Client来自 SDK
  • C++ 标准是否指定了编译器的 STL 实现细节?

    在写答案时this https stackoverflow com questions 30909296 can you put a pimpl class inside a vector我遇到了一个有趣的情况 这个问题演示了这样一种情况

随机推荐

  • 并发编程系列之volatile内存语义

    前言 前面介绍顺序一致性模型时 我们提到了程序如果正确的同步就会具备顺序一致性 这里所说的同步泛指广义上的同步 其中包括就包括同步原语volatile 那么volatile声明的变量为什么就能保证同步呢 这又是如何实现的呢 今天就让我们一起
  • js混淆与反混淆

    介绍几种js混淆方式 1 eval混淆 js中的eval 方法 就是一个js语言的执行器 它能把字符串解析成javascript的语法进行执行 简单来说就是把原本的js代码当成eval方法的参数 据说此方法出来的第一天就被破解了 修改一下代
  • 用java实现数组单元素操作

    题目 1 如果字符串中的字符为大写字母 则转换为小写字母 2 如果字符串中的字符为小写字母 则直接输出 3 如果字符串中的字符不是字母 则过滤掉 首先明确如何输入字符数组 import java util Scanner class put
  • Web项目中使用容器对象

    要是使用Maven构建项目 首先需要加入Maven依赖
  • 以太坊的RPC机制

    1 go语言的RPC机制 RPC Remote Procedure Call 远程过程调用 是一种通过网络从远程计算机程序上请求服 务 而不需要了解底层网络细节的应用程序通信协议 RPC协议构建于TCP或UDP 或者是 HTTP 之上 允许
  • linux set o,Linux Set 和 shopt 命令

    用set命令可以设置各种shell选项或者列 出shell变量 单个选项设置常用的特性 在某些选项之后 o参数将特殊特性打开 在某些选项之后使用 o参数将关闭某些特性 不带任何参数的set命 令将显示shell的全部变量 除非遇到非法的选项
  • 报这样的错误 error: #35: #error directive: "Please select first th 解决方法

    右键点击工程名 选择第一个options for target 下面选择C C 在define文本框中输入 USE STDPERIPH DRIVER STM32F10X MD MD根据你选择的机种更换为LD或HD
  • 暴击事件

    在许多场景中 我们可能会遇到需要处理一种快速多次触发某事件 并处于某种阈值时 执行某一指定操作 例如 双击 即快速按鼠标左键两次 或更多击 连按键盘某键 某方法被执行数次等 其中 双击有对应的事件可以注册 然而 更多的情况是没有的类似事件方
  • JS中'true'==true为什么返回false

    相等操作符在转换不同的数据类型时 相等和不相等操作符遵循下列基本规则 如果有一个操作数是布尔值 则在比较相等性之前先将其转换为数值 false转换为0 而true转换为1 如果一个操作数是字符串 另一个操作数是数值 在比较相等性之前先将字符
  • OLED拼接屏连接方法,需要注意哪些事项?

    OLED拼接屏是由多个OLED屏幕拼接而成的大屏幕 可以用于展示大型广告 信息发布 舞台背景等场合 在拼接OLED屏幕时 需要注意接法 以确保整个屏幕的显示效果和稳定性 首先 需要选择合适的OLED屏幕 一般来说 拼接屏幕的每个单元都应该是
  • PHP 23种设计模式

    设计模式的目的 重用性 相同功能的代码 不用多次编写 可读性 编程规范性 便于其他程序员的阅读和理解 可扩展性 当需要增加新的功能时 非常的方便 称为可维护 可靠性 当我们增加新的功能后 对原来的功能没有影响 使程序呈现高内聚 低耦合的特性
  • redis 3.0的集群部署

    文章转载自 http hot66hot iteye com blog 2050676 转载请注明出处 http hot66hot iteye com admin blogs 2050676 最近研究redis cluster 正好搭建了一个
  • 使用ChatGPT的gpt-3.5-turbo模型, PHP接入代码

  • CAN 总线通信 简要概括

    CAN 通信总线协议 简要概括 CAN 介绍 CAN 类型 高速 CAN 低速 CAN CAN 总线系统结构 CAN bus通信帧 CAN 基本数据帧结构 CAN 硬件设计 CAN 介绍 CAN Controller Area Networ
  • 2022年Python面试题汇总【面试官爱问】

    2022年Python面试题汇总 常问 1 请你讲讲python获取输入的方式 以及python如何打开文件 2 Python数据处理的常用函数 3 请你说说python传参传引用 4 请你说说python和java的区别 5 Python
  • IPv6知识概述 - IPv6地址

    IPv6知识概述 IPv6地址 IPv6地址表示 根据RFC4291 IPv6地址有3中格式 首选格式 压缩表示和内嵌IPv4地址的IPv6地址表示 首选格式 IPv6的地址长度是128位 bit 将这128位的地址按每16位划分为一个段
  • wincc怎么做一个弹出画面_Wincc如何利用单个弹出窗口画面的模板,来实现调用多组画面参数?...

    点击上方蓝色字 小叔聊自控 在后台回复关键字 画面脚本 即可获得本次视频中的所有文件及项目包 以下视频中包含本期所有内容 大家好 我是小叔 今天我们来了解一下Wincc如何利用单个弹出窗口的画面模板 来实现调用多组画面参数的方法 怎么来理解
  • Unity版本更新之后IOS审核提示机型适配变少

    之前用2020 3 1提交IOS白包 后来更新版本后使用2020 3 10打包的 提示适配 机器变少了 We identified one or more issues with a recent submission for App St
  • 问题集锦~

    1 Wireshark抓包过程遇到的一点小问题 在使用wireshark进行抓包时 发现目标为本机时 无法抓包 这是由于wireshark并不会抓取本机loop的流量 只会抓取流经网卡的流量 如果需要使用wireshark抓取本机的数据包
  • Q_DECLARE_PRIVATE与Q_DECLARE_PUBLIC

    Q DECLARE PRIVATE与Q DECLARE PUBLIC 这两个宏在Qt的源码中随处可见 重要性不言而喻 在 部落格的 Inside Qt Series 系列文章中 他用了3篇文章来讲这个问题 因为 QObject 本身比较复杂