Q_DECLARE_PRIVATE与Q_DECLARE_PUBLIC
这两个宏在Qt的源码中随处可见,重要性不言而喻。在 部落格的 Inside Qt Series 系列文章中,他用了3篇文章来讲这个问题。 因为 QObject 本身比较复杂,这两个宏和一个复杂的东西搅和到一块,还真是不好理解。不过幸好,这个两个宏和QObject 没有必然的联系。故接下来,忘记 QObject,看一个普通的C++的类 例子类 QtServiceController 定义: class QtServiceController |
宏定义
宏定义在 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的更多相关文章
- 6、Qt Meta Object system 学习
原文地址:http://blog.csdn.net/ilvu999/article/details/8049908 使用 meta object system 继承自 QOject 类定义中添加 Q_ ...
- Qt Meta Object system 学习
原文地址:http://blog.csdn.net/ilvu999/article/details/8049908 使用 meta object system 继承自 QOject 类定义中添加 Q_ ...
- Qt QObject
[1]Qt的QObject 1.测试代码如下: #include<QApplication> #include<QPushButton> #include<QDebug& ...
- 深入了解Qt(一)之QObject
深入了解Qt主要内容来源于Inside Qt系列,本文做了部分删改,以便于理解.在此向原作者表示感谢! QObject这个 class 是 QT 对象模型的核心,关于对象模型可以阅读C++对象模型详解 ...
- Qt源码分析之QObject
原文:http://blog.csdn.net/oowgsoo/article/details/1529284 我感觉oowgsoo兄弟写的分析相当透彻,赞! 1.试验代码: #include < ...
- Qt之四方分割器QuadSplitter
在Qt经常会用到分割器QSplitter,可以对多个控件进行水平或者垂直分割,但有一些特殊的需求无法满足,比如:四方分割...QuadSplitter是qt-apps里面的一个应用,挺不错的,拿来和大 ...
- d指针在Qt上的应用及实现(d指针能实现二进制兼容)
Qt为了使其动态库最大程度上实现二进制兼容,引入了d指针的概念.那么为什么d指针能实现二进制兼容呢?为了回答这个问题,首先弄清楚什么是二进制兼容?所谓二进制兼容动态库,指的是一个在老版本库下运行的程序 ...
- Q_D宏
Qt 源码中有很多Q_Q和Q_D宏,使用这些宏的地方总会看到有q指针和d指针,查了查KDE文档,大体搞清了其中的机理,欧也!Qt的这些私有数据访问策略还是挺值得借鉴.下面就简单总结一下. 访问器 , ...
- Inside Qt Series (全集)
Inside Qt 系列 QObject这个 class 是 QT 对象模型的核心,绝大部分的 QT 类都是从这个类继承而来.这个模型的中心特征就是一个叫做信号和槽(signaland slot)的机 ...
随机推荐
- 【MySQL】 DB 回滚崩溃案例一则
一台mysql数据库在多次断电之后,长时间等待未果直接重启mysql 服务.之后错误日志中报错: 170119 :: InnoDB: Error: page log sequence number I ...
- vue---进行post和get请求
参考文档: https://www.jb51.net/article/125717.htm 使用axios <script src="https://unpkg.com/axios/d ...
- Django---项目如何创建
首先是安装好Django,找到 Scripts 目录配置环境变量: 只要添加到环境变量,在任何目录执行 django-admin startproject mysite 就可以创建 Django 程序 ...
- 关于 Java 泛型的一些有趣的例子
有以下的代码: try { ArrayList<String> lstA = new ArrayList<String>(); ArrayList<Integer> ...
- 启动了SSH服务后,一定要关闭Telnet服务
https://baike.baidu.com/item/ssh/10407 https://baike.baidu.com/item/Telnet/810597
- 隐马尔可夫(HMM)
https://www.zhihu.com/question/20962240 作者:Yang Eninala链接:https://www.zhihu.com/question/20962240/an ...
- sql根据某一个字段重复只取第一条数据
比如上图,取3,4行记录的第一行也就是3行,而不返回4行. 使用分析函数row_number() over (partiion by ... order by ...)来进行分组编号,然后取分组标号值 ...
- Python开发【笔记】:what?进程queue还能生产出线程!
进程queue底层用线程传输数据 import threading import multiprocessing def main(): queue = multiprocessing.Queue() ...
- kubernetes实战(十一):k8s使用openLDAP统一认证
1.基本概念 为了方便管理和集成jenkins,k8s.harbor.jenkins均使用openLDAP统一认证. 2.部署openLDAP 此处将openLDAP部署在k8s上,openLDAP可 ...
- python操作docx学习资料
1.博客 (1)写入参考 https://www.cnblogs.com/rencm/p/6285304.html (2)读取参考 http://www.cnblogs.com/zhanghongfe ...