关于Qt中的Q_D,Q_Q
扒了下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相关推荐
- Qt信息隐藏(Q_D/Q_Q)介绍
目录: 1:基本介绍与二进制兼容 2:二进制兼容的设计原则 3:常见c++/qt信息隐藏 4:Q_Q,Q_D介绍 5:定制可编辑treewidget与如何访问基类的Private 6:总结 1:基本介 ...
- Qt中的d指针和q指针
概述 如果程序从一个以前版本的库动态链接到新版本的库之后,能够继续正常运行,而不需要重新编译,那么我们就说这个库是二进制兼容的. 如果一个程序需要重新编译来运行一个新版本的库,但是不需要对程序的源代码 ...
- QT中的D指针与Q指针
了解QT中引入D指针的初衷前需要了解下二进制兼容 1. 什么是二进制兼容 二进制兼容是针对动态链接库而言的,如果你的源代码已经编译成为可执行文件了,其中你调用了一些动态库,后来你为这个动态库进行了更新 ...
- QT 中QTimer 和 startTimer()的区别
最需要注意一点 请注意,QTimer的准确性取决于底层操作系统和硬件.timerType参数允许您自定义计时器的准确性.有关不同计时器类型的信息,请参见Qt::TimerType.大多数平台支持20毫 ...
- QT 中使用 OpenCv 的 CascadeClassifier 报错
问题 在 QT 中调用 OpenCv 的 CascadeClassifier 进行人脸框检测的时候,在构造函数中进行检测器的初始化,随后调用相机读取图片的时候就会报错,报的错误是 Segment Fa ...
- 【Qt】Qt中使用ssl时报错:qt.network.ssl: QSslSocket: cannot resolve SSLv2_client_method
一.问题 在Qt中使用https,运行时报错: qt.network.ssl: QSslSocket: cannot resolve SSLv2_client_method 二.原因分析 SSLv2由 ...
- Qt中两种定时器用法
在Qt中使用定时器有两种方法,一种是使用QObiect类的定时器:一种是使用QTimer类.定时器的精确性依赖于操作系统和硬件,大多数平台支持20ms的精确度. 1.QObject类的定时器 QObj ...
- Qt中的 Size Hints 和 Size Policies
sizeHint 这个属性所保存的 QSize 类型的值是一个被推荐给窗口或其它组件(为了方便下面统称为widget)的尺寸,也就是说一个 widget 该有多大,它的一个参考来源就是这个 sizeH ...
- Qt中使用多线程的一些心得(一)——继承QThread的多线程使用方法
一 前言 二Qt多线程方法一 继承QThread 2.1使用多线程的原因分析 2.2 写一个继承于QThread的线程 三 总结 一 前言 本篇文章部分内容参考了该博文:传送门. Qt中有两种 ...
最新文章
- 吴恩达机器学习笔记 —— 8 正则化
- CNI (Container Network Interface)
- 什么是迭代器,JS如何实现迭代器
- 神经网络模型遇到瓶颈?这些Tricks让你相见恨晚!
- cipher java aes 模式_java – 为什么我的AES Cipher在init的DECRYPT_MODE上抛出一个InvalidKeyException...
- 这三种程序员,是时代的溺水者
- 使用无锁队列(环形缓冲区)注意事项
- 微电子学与计算机期刊2019,微电子与通信工程学院研究生两篇论文被人工智能顶级会议AAAI 2019接收...
- 文本对比工具哪些好用?竟然有在线的。真香。
- 手机qq下载文件地址
- 金融计算机加权平均,加权平均
- 极客云原生营-云原生知识
- ns3网络模拟器使用相关问题
- 可扩展标记语言XML(淅淅沥沥的小雨)
- 41首送别诗词,首首经典,值得为孩子们收藏!
- 超频技术之内存“时序”重要参数设置解说
- 【狂神说】——Spring笔记(全)
- Unity制作随机数字抽奖小案例
- Centos 安装sl 命令
- 歌谣学前端之箭头函数2