最近看到**有用到了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...