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的原因

Q_DECLARE_PRIVATE与Q_DECLARE_PUBLIC的更多相关文章

  1. 6、Qt Meta Object system 学习

    原文地址:http://blog.csdn.net/ilvu999/article/details/8049908 使用 meta object system 继承自 QOject 类定义中添加 Q_ ...

  2. Qt Meta Object system 学习

    原文地址:http://blog.csdn.net/ilvu999/article/details/8049908 使用 meta object system 继承自 QOject 类定义中添加 Q_ ...

  3. Qt QObject

    [1]Qt的QObject 1.测试代码如下: #include<QApplication> #include<QPushButton> #include<QDebug& ...

  4. 深入了解Qt(一)之QObject

    深入了解Qt主要内容来源于Inside Qt系列,本文做了部分删改,以便于理解.在此向原作者表示感谢! QObject这个 class 是 QT 对象模型的核心,关于对象模型可以阅读C++对象模型详解 ...

  5. Qt源码分析之QObject

    原文:http://blog.csdn.net/oowgsoo/article/details/1529284 我感觉oowgsoo兄弟写的分析相当透彻,赞! 1.试验代码: #include < ...

  6. Qt之四方分割器QuadSplitter

    在Qt经常会用到分割器QSplitter,可以对多个控件进行水平或者垂直分割,但有一些特殊的需求无法满足,比如:四方分割...QuadSplitter是qt-apps里面的一个应用,挺不错的,拿来和大 ...

  7. d指针在Qt上的应用及实现(d指针能实现二进制兼容)

    Qt为了使其动态库最大程度上实现二进制兼容,引入了d指针的概念.那么为什么d指针能实现二进制兼容呢?为了回答这个问题,首先弄清楚什么是二进制兼容?所谓二进制兼容动态库,指的是一个在老版本库下运行的程序 ...

  8. Q_D宏

    Qt 源码中有很多Q_Q和Q_D宏,使用这些宏的地方总会看到有q指针和d指针,查了查KDE文档,大体搞清了其中的机理,欧也!Qt的这些私有数据访问策略还是挺值得借鉴.下面就简单总结一下. 访问器 , ...

  9. Inside Qt Series (全集)

    Inside Qt 系列 QObject这个 class 是 QT 对象模型的核心,绝大部分的 QT 类都是从这个类继承而来.这个模型的中心特征就是一个叫做信号和槽(signaland slot)的机 ...

随机推荐

  1. 为自定义的View添加长按事件

    以前开发画板组件时,要添加一个长按监听事件,这个画板实际上就是继承自View的一个自定义组件. 首先,设置好长按事件发生时要触发的操作: private class LongPressRunnable ...

  2. ThinkCMF----调用指定栏目的文章列表

    做项目的时候,在用ThinkCMF在首页调用指定的栏目文章,但是没有找到好的方法,就自己写了一个. 但是又不想写标签,就在公用方法里面实现了:找到common.php 操作数据库,要用到think的控 ...

  3. myeclipse乱码/GBK只支持中文

    Windows>>Pereferences>>General>Editors>>Spelling>>Encoding选项下选择other,然后输入 ...

  4. poj3304 Segments【计算几何】

    C - Segments POJ - 3304 最近开始刷计算几何了 公式好多完全不会 数学不行 几何不行 记忆力不行 当机 查的题解 就当复习吧 这套专题拿来熟悉一下计算几何模板 #include ...

  5. oracle 日期格式化和数据去重

    1.获取系统日期: select sysdate as date1 from dual: 当前时间减去7分钟的时间 select sysdate,sysdate - interval '7' MINU ...

  6. AjaxAnywhere的用法(FORWARD)

    AjaxAnywhere的用法   ajaxanywhere 总结:1,简介AjaxAnywhere被设计成能够把任何一套现存的JSP组件转换成AJAX感知组件而不需要复杂的JavaScript编码. ...

  7. spring boot+mybatis 系列

    https://blog.csdn.net/linxingliang/article/details/52324937 https://www.cnblogs.com/a8457013/p/90749 ...

  8. MySQL在linux上的二进制安装方法

    建组.建用户: [root@dbking mysql]# groupadd mysql [root@dbking mysql]# useradd -g mysql mysql 解压安装程序: [roo ...

  9. date 命令之日期和秒数转换

    时间转为秒数 date -d "2012-11-12 13:00:00" +"%s" 描述转为日期 date -d@1352692800 +"%Y-% ...

  10. php 实现 二维码 扫描登录

    本人简单实现的示例,使用任意二维码工具打开二维码对应链接 http://www.54php.cn/demo1/scan 原理介绍: 第一步:访问登录页面,生成唯一key,例如MkhjDFL=,并且将此 ...