扒了下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_OBJECT
Q_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 QWindow
uint 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_MAC
void cleanupNativePopup();
bool showNativePopup();
#endif
QAbstractItemModel *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的接口;