扒了下QComboBox的源码,里面使用了大量的Q_D,Q_Q宏,记录一下:

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

看看d_func和q_func:

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 *>(qGetPtrHelper(Dptr)); } \inline const Class##Private* d_func() const { return reinterpret_cast<const Class##Private *>(qGetPtrHelper(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;

对于QComboBox来说,Q_D(const QComboBox)相当于是:

QComboBoxPrivate *const d = reinterpret_cast<QComboBoxPrivate *>(qGetPtrHelper(d_ptr));

Q_Q(QComboBox) 相当于是:

QComboBox *const q = static_cast<const Class *>(q_ptr);

d_prt定义在:

class Q_CORE_EXPORT QObject
{Q_OBJECTQ_PROPERTY(QString objectName READ objectName WRITE setObjectName NOTIFY objectNameChanged)Q_DECLARE_PRIVATE(QObject)/* 此处省略其余定义 */
protected:QScopedPointer<QObjectData> d_ptr;

d_ptr是在:

QComboBox::QComboBox(QWidget *parent): QWidget(*new QComboBoxPrivate(), parent, 0)
{Q_D(QComboBox);d->init();
}

这里new QComboBoxPrivate(),一层一层地往下传递,最后会传递到:

QObject::QObject(QObjectPrivate &dd, QObject *parent): d_ptr(&dd)
{Q_D(QObject);d_ptr->q_ptr = this;
.....
}

这里QObjectd::d_ptr就值了。dptr->q_ptr保存了当前控件的this指针。因为QComboBoxPrivate继承QWidgetPrivate,QWidgetPrivate继承QObjectPrivate,QObjectPrivate继承 QObjectData, QObjectData的定义如下:

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 QWindowuint unused : 25;int postedEvents;QDynamicMetaObjectData *metaObject;QMetaObject *dynamicMetaObject() const;
};

回到上文,

Q_D(const QComboBox)相当于是:

QComboBoxPrivate *const d = reinterpret_cast<QComboBoxPrivate *>(qGetPtrHelper(d_ptr));

也就是将d_ptr转换成具体的QComboBoxPrivate类,控件的数据都保存在它对应的Private类里,例如QComboBox的数据都保存在:

class Q_AUTOTEST_EXPORT QComboBoxPrivate : public QWidgetPrivate
{Q_DECLARE_PUBLIC(QComboBox)
public:QComboBoxPrivate();~QComboBoxPrivate();void init();/* 此处省略相关声明 */#ifdef Q_OS_MACvoid cleanupNativePopup();bool showNativePopup();
#endifQAbstractItemModel *model;QLineEdit *lineEdit;QComboBoxPrivateContainer *container;QComboBox::InsertPolicy insertPolicy;QComboBox::SizeAdjustPolicy sizeAdjustPolicy;int minimumContentsLength;QSize iconSize;/* 此处省略相关声明 */static QPalette viewContainerPalette(QComboBox *cmb){ return cmb->d_func()->viewContainer()->palette(); }
};

QComboBox需要访问数据时,先通过Q_D,将d_ptr转换成QComboBoxPrivate的指针,再访问数据;

而QComboBoxPrivate需要访问QComboBox的接口时,先通过Q_Q,将q_ptr转换成QComboBox指针,再调用QComboBox的接口;

关于Qt中的Q_D,Q_Q相关推荐

  1. Qt信息隐藏(Q_D/Q_Q)介绍

    目录: 1:基本介绍与二进制兼容 2:二进制兼容的设计原则 3:常见c++/qt信息隐藏 4:Q_Q,Q_D介绍 5:定制可编辑treewidget与如何访问基类的Private 6:总结 1:基本介 ...

  2. Qt中的d指针和q指针

    概述 如果程序从一个以前版本的库动态链接到新版本的库之后,能够继续正常运行,而不需要重新编译,那么我们就说这个库是二进制兼容的. 如果一个程序需要重新编译来运行一个新版本的库,但是不需要对程序的源代码 ...

  3. QT中的D指针与Q指针

    了解QT中引入D指针的初衷前需要了解下二进制兼容 1. 什么是二进制兼容 二进制兼容是针对动态链接库而言的,如果你的源代码已经编译成为可执行文件了,其中你调用了一些动态库,后来你为这个动态库进行了更新 ...

  4. QT 中QTimer 和 startTimer()的区别

    最需要注意一点 请注意,QTimer的准确性取决于底层操作系统和硬件.timerType参数允许您自定义计时器的准确性.有关不同计时器类型的信息,请参见Qt::TimerType.大多数平台支持20毫 ...

  5. QT 中使用 OpenCv 的 CascadeClassifier 报错

    问题 在 QT 中调用 OpenCv 的 CascadeClassifier 进行人脸框检测的时候,在构造函数中进行检测器的初始化,随后调用相机读取图片的时候就会报错,报的错误是 Segment Fa ...

  6. 【Qt】Qt中使用ssl时报错:qt.network.ssl: QSslSocket: cannot resolve SSLv2_client_method

    一.问题 在Qt中使用https,运行时报错: qt.network.ssl: QSslSocket: cannot resolve SSLv2_client_method 二.原因分析 SSLv2由 ...

  7. Qt中两种定时器用法

    在Qt中使用定时器有两种方法,一种是使用QObiect类的定时器:一种是使用QTimer类.定时器的精确性依赖于操作系统和硬件,大多数平台支持20ms的精确度. 1.QObject类的定时器 QObj ...

  8. Qt中的 Size Hints 和 Size Policies

    sizeHint 这个属性所保存的 QSize 类型的值是一个被推荐给窗口或其它组件(为了方便下面统称为widget)的尺寸,也就是说一个 widget 该有多大,它的一个参考来源就是这个 sizeH ...

  9. Qt中使用多线程的一些心得(一)——继承QThread的多线程使用方法

    一 前言 二Qt多线程方法一 继承QThread 2.1使用多线程的原因分析 2.2 写一个继承于QThread的线程 三 总结 一 前言   本篇文章部分内容参考了该博文:传送门.   Qt中有两种 ...

最新文章

  1. Qt之两种初始化QListWidget的方法
  2. java反射机制(三)---java的反射和代理实现IOC模式 模拟spring
  3. android应用程序的组成部分
  4. eclipse批量修改package、import中的包名
  5. 【项目经验】如果想在mapper.xml文件中的一个标签中写多条sql语句,则需要在jdbc的配置文件中稍做配置
  6. 使用 ServiceStack 构建跨平台 Web 服务(转)
  7. 16张图带你吃透高性能 Redis 集群
  8. c++ 结构体初始化_单片机C语言 - 基于结构体的面向对象编程技巧
  9. 【金融申请评分卡】数据准备 - 造衍生变量
  10. 非资深玩家留言频率限制(1024秒限制)
  11. DNS 服务器 4013警告信息的解决
  12. 腾讯业务架构:六大事业群
  13. Flink WaterMark 详解及结合 WaterMark 处理延迟数据
  14. MTK LK阶段 display框架
  15. 月薪翻20倍,从小编辑到百度高级产品经理,我是如何打怪升级的
  16. ps如何把自己的图与样机结合_如何利用PS制作贴图样机那
  17. 天耀18期 -09.数组-排序【作业】.doc
  18. python樱花树代码_Python画樱花树
  19. 中国流量排名前一百名网站
  20. LC并联谐振电路设计

热门文章

  1. “购物返现积分兑换”——区块链思维的购物返利方式
  2. matlab 找到数组中第一个不连续点_1.基础知识(1) Matlab基础知识
  3. 在珠海C1驾照能开什么车?
  4. 解决轮播图图片大小不一的问题!
  5. TCP socket 编程示例
  6. windows编译linux内核
  7. 聚氨酯泡沫申请ASTM E84 Class A防火级别测试
  8. 分页(联表情况)搜索
  9. IIS应用程序池启用32位导致服务不可用的503错误
  10. 深度学习中的知识蒸馏技术(上)