QT中的數據指針

 在此中以QGLWidget爲例作爲一個說明:

在源碼頭文件中看到該類的聲明部分,第二行就是

DECLARE_PRIVATE(QGLWidget)

這是一個宏的定義,展開以後是這個樣子的:

#define Q_DECLARE_PRIVATE(Class) /
    inline Class##Private* d_func() { return reinterpret_cast<Class##Private *>(d_ptr); } /
    inline const Class##Private* d_func() const { return reinterpret_cast<const Class##Private *>(d_ptr); } /
    friend class Class##Private;

也就是說定義了一個內聯函數去得到一個私有數據成員的指針,大家在這裏會得到將d_ptr強制轉換而來的一個指針。指針的類型爲QGLWidgetPrivate(這裏的##是將前後連接起來的,編譯器所完成的工作,我這裏是以QGLWidget爲例的,所以是QGLWidgetPrivate數據),我在看這裏的時候有個疑問是這個數據指針存在於哪裏,什麼時候被分配了內存空間的。

下面是我的解釋:

我們在調用QGLWidget的構造函數時,會先調用基類即QWidget的構造函數,我們其實是這樣調用的:

QGLWidget::QGLWidget(QWidget *parent, const QGLWidget* shareWidget, Qt::WindowFlags f)
    : QWidget(*(new QGLWidgetPrivate), parent, f | Qt::MSWindowsOwnDC)

大家看到這裏在構造QWidget時,給數據成員分配了內存空間,而這個構造函數實際上是按下面定義的:

QWidget::QWidget(QWidgetPrivate &dd, QWidget* parent, Qt::WindowFlags f)
    : QObject(dd, 0), QPaintDevice()
{
    d_func()->init(parent, f);
}

依此類推,我們有理由相信,這個數據指針最終指向的是QObject中所定義的一個指針d_ptr。另外,我們還可以看到,這些最後帶有Private的類也是有繼承關係的,這就解釋了,在各個類中d_ptr是如何呈現自身的特性的。

另外還有一點就是QGLWidgetPrivate中的數據又是在何時被初始化的呢,是在一個init函數中被初始化的,其調用如下顯示:

QGLWidget::QGLWidget(QWidget *parent, const QGLWidget* shareWidget, Qt::WindowFlags f)
    : QWidget(*(new QGLWidgetPrivate), parent, f | Qt::MSWindowsOwnDC)
{
    Q_D(QGLWidget);     //這裏獲得了數據指針(據前面的解釋)
    setAttribute(Qt::WA_PaintOnScreen);
    setAttribute(Qt::WA_NoSystemBackground);
    setAutoFillBackground(true); // for compatibility
    d->init(new QGLContext(QGLFormat::defaultFormat(), this), shareWidget); //這裏對其進行初始化
}

還有兩點需要注意的是,兩個宏:

#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;

這個宏被用於數據類中調用去得到其所對應的實體類(例如:QGLWidgetPrivate對應於QGLWidget)

#define Q_DECLARE_PRIVATE(Class) /
    inline Class##Private* d_func() { return reinterpret_cast<Class##Private *>(d_ptr); } /
    inline const Class##Private* d_func() const { return reinterpret_cast<const Class##Private *>(d_ptr); } /
    friend class Class##Private;

這個宏剛好與之前的宏相反,用於實體類用於得對應的數據類成員。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章