扒了下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. 吴恩达机器学习笔记 —— 8 正则化
  2. CNI (Container Network Interface)
  3. 什么是迭代器,JS如何实现迭代器
  4. 神经网络模型遇到瓶颈?这些Tricks让你相见恨晚!
  5. cipher java aes 模式_java – 为什么我的AES Cipher在init的DECRYPT_MODE上抛出一个InvalidKeyException...
  6. 这三种程序员,是时代的溺水者
  7. 使用无锁队列(环形缓冲区)注意事项
  8. 微电子学与计算机期刊2019,微电子与通信工程学院研究生两篇论文被人工智能顶级会议AAAI 2019接收...
  9. 文本对比工具哪些好用?竟然有在线的。真香。
  10. 手机qq下载文件地址
  11. 金融计算机加权平均,加权平均
  12. 极客云原生营-云原生知识
  13. ns3网络模拟器使用相关问题
  14. 可扩展标记语言XML(淅淅沥沥的小雨)
  15. 41首送别诗词,首首经典,值得为孩子们收藏!
  16. 超频技术之内存“时序”重要参数设置解说
  17. 【狂神说】——Spring笔记(全)
  18. Unity制作随机数字抽奖小案例
  19. Centos 安装sl 命令
  20. 歌谣学前端之箭头函数2

热门文章

  1. c语言中int x=0101,二进制安全_C语言中数据类型
  2. centos7 文件属性权限设置
  3. A1039 Course List for Student (25 分)
  4. 伟大的Hessian!
  5. Intel Purley feature: RDT PTT MPX...
  6. 认证,oAuth!!!
  7. iMX6ULL学习(三)
  8. 改变自我,为成功伏笔
  9. CSAPP:计算机基本结构与CPU内部构造
  10. MFC 对话框 背景图片 以及消除 字体重影 字体重叠