資料隱藏之Qt中d指標詳解

2021-08-07 10:13:32 字數 3615 閱讀 9792

最近看到**有用到了qt中的q_d指標,就去學習了下,發現真的很好用,因此寫一篇文章總結下。

class cstudent

;

如果我們這個類屬於乙個動態庫,那麼向外部提供乙個dll時,就會暴露我類的資料結構,使用者便會知道,原來姓名是string型別,年齡是int型別等等,這是我不想看到的,也不符合我把其設定為private的初衷。

那怎麼才能解決上面的問題呢?也許我們可以這麼做:

class cstudentdate;

class cstudent

;class cstudentdate

;

我們將cstudent的資料全部放到他的資料管理類中,將其資料管理類全部放到其cpp中實現,這樣即使你像人家提供你的dll和.h檔案也不會暴露你的成員的資料型別。這就是一種資料隱藏方式。其優點是隱藏了我們不想透露的資料資訊,而且我們即使新增資料項如在新增乙個班級成員等也不會影響cstudent類的大小。能做到二進位制相容。

以下內容來自:

如上圖,這個是qt根結點的指標的一般形式,下面來看看非根結點的一般形式,

注意這裡qwidge派生自qobject,它裡面沒有d_ptr,但是它的成員函式可以訪問d_ptr,因為 d_ptr是保護成員,且它的物件模型包含 d_ptr(這是因為派生類繼承父類的所有成員)。

下面我們來看看qt對上述兩種情況是怎麼實現的:

qobject.h檔案:

qobjectdata ;

class q_core_export qobject

;

如上,在這裡我算去了其他的項,只保留了於d_ptr有關的項,首先來看看q_declare_private(qobject)是什麼:

inline class##private* d_func()  \  

inline const class##private* d_func() const \

friend class class##private;

根據巨集定義,則q_declare_private(qobject)翻譯如下:

inline qobjectprivate *d_func()  

inline const qobjectprivate *d_func() const  

friend class qobjectprivate;

再來看看qgetptrhelper的定義:

template static inline t *qgetptrhelper(t *ptr)  

再來看qscopepointer,它類似於智慧型指標,這樣不用關心 d_ptr的釋放,當離開qscopepointer的作用範圍,qscopepointer會自動釋放d_ptr指向的堆記憶體,那麼這個指標是什麼時候生成的呢?q_ptr又是什麼時候賦值的呢?讓我們來看看qobject.cpp的實現:

qobject::qobject(qobject *parent)  

: d_ptr(new qobjectprivate)

qobject::qobject(qobjectprivate &dd, qobject *parent)

: d_ptr(&dd)

我們看第乙個建構函式,對於根結點的d_ptr指向new qobjectprivate,而qobjectprivate派生自qobjectdata,那麼q_d(qobject)巨集表示什麼意思呢?

#define q_d(class) class##private * const d = d_func()  

q_d(qobject);翻譯如下:

qobjectprivate * const d = d_func();

不難看出q_d(qobject);定義了乙個qobjectprivate的常量指標,指向d_func() 的返回值,而該返回值,正是d_ptr(見標頭檔案 d_func()的定義),因此同過q_d巨集我們就可以訪問d指標了。

對於第二個建構函式稍後介紹,下面來看看非根結點的d_ptr的實現情況:

標頭檔案:

class q_core_export qobjectprivate : public qobjectdata  

;

class q_gui_export qwidgetprivate : public qobjectprivate

;

class q_gui_export qwidget : public qobject

;

我們首先來看看q_declare_public巨集:

#define q_declare_public(class)                                    \  

inline class* q_func() \

inline const class* q_func() const \

friend class class;

根據巨集定義,q_declare_public(qobject)翻譯如下:

inline qobject *q_func()

inline const qobject *q_func() const

friend class qobject;

q_declare_public(qwidget)翻譯如下:

inline qwidget *q_func()

inline const qwidget *q_func() const

friend class qwidget;

注意這裡的q_ptr是在qobjectdata裡公有宣告的,qobjectprivate,qwidgetprivate都派生或間接派生自qobjectdata,所以可以訪問q_ptr。

接下來看q_declare_private(qwidget)的翻譯:

inline qwidgetprivate *d_func()  

inline const qwidgetprivate *d_func() const

friend class qwidgetprivate;

接下來看看qwidget的建構函式的實現:

qwidget::qwidget(qwidget *parent, qt::windowflags f)  

: qobject(*new qwidgetprivate, 0)

看到qobject(*new qwidgetprivate, 0)這裡呼叫了qobject的第二個建構函式,將d_ptr指向new qwidgetprivate所指向的堆記憶體。

QT中的資料指標

在此中以qglwidget為例作為乙個說明 在原始碼標頭檔案中看到該類的宣告部分,第二行就是 declare private qglwidget 這是乙個巨集的定義,展開以後是這個樣子的 define q declare private class inline class private d fu...

如何在指標中隱藏資料?

編寫 c 語言 時,指標無處不在。我們可以稍微額外利用指標,在它們內部暗中儲存一些額外資訊。為實現這一技巧,我們利用了資料在記憶體中的自然對齊特性。記憶體中的資料並非儲存在任意位址。處理器通常按照其字大小相同的塊讀取記憶體資料 那麼考慮到效率因素,編譯器會按照塊大小的整數倍對記憶體中的實體進行位址對...

Qt 中的智慧型指標之QSharedPointer

c 11 標準中的有提供智慧型指標,在 qt 中也提供了類似的替代功能,並且比 c 11 標準中提供的功能還要強大,所以如果我們使用 qt 作為基礎庫,那麼就沒有必要使用c 11 的智慧型指標。qt 的智慧型指標包括 qsharedpointer qscopedpointer qscopedarra...