Qt核心剖析 資訊隱藏 3

2021-06-20 15:43:03 字數 2972 閱讀 3015

原始出處 、作者資訊和本宣告。否則將追究法律責任。

前面我們已經看到了怎樣使用標準的 c++ **以及 qt 提供的 api 來達到資訊隱藏這一目標。下面我們來看一下 qt 是如何實現的。

還是以 qobject 的源**作為例子。先開啟 qobject.h,找到 qobjectdata 這個類的宣告。具體**如下所示:

qobjectdata ;  

然後在下面就可以找到 qobject 的宣告:

class

qobject  

注意,這裡我們只是列出了我們所需要的**,並且我的 qt 版本是 2010.03。這部分**可能會隨著不同的 qt 版本所有不同。

首先先了解一下 qt 的設計思路。既然每個類都應該把自己的資料放在乙個 private 類中,那麼,為什麼不把這個操作放在幾乎所有類的父類 qobject 中呢?所以,qt 實際上是用了這樣乙個思路,實現了我們前面介紹的資料隱藏機制。

首先回憶一下,我們前面說的 d-pointer 需要有乙個 private 或者 protected 的指向自己資料類的指標。在 qobject 中,

qscopedpointerd_ptr; 

就扮演了這麼乙個角色。或許,你可以把它理解成

qobjectdata *d_ptr; 

這不就和我們前面說的 d-pointer 技術差不多了?qscopedpointer 是 qt 提供的乙個輔助類,這個類儲存有乙個指標,它的行為類似於一種智慧型指標:它能夠保證在這個作用域結束後,裡面的所有指標都能夠被自動 delete 掉。也就是說,它其實就是乙個比普通指標更多功能的指標。而這個指標被宣告成 protected 的,也就是只有它本身以及其子類才能夠訪問到它。這就提供了讓子類不必須宣告這個 d-pointer 的可能。

那麼,前面我們說,qobjectdata 這種資料類不應該放在公開的標頭檔案中,可 qt 怎麼把它放進來了呢?這樣做的用途是,qobject 的子類的資料類都可能繼承自這個 qobjectdata。這個類有乙個純虛的析構函式。沒有實現**,保證了這個類不能被初始化;虛的析構函式,保證了其子類都能夠被正確的析構。

回到我們前面說明的 q_declare_private 這個巨集:

#define q_declare_private(class) \  

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; 

清楚是清楚,只是這個 qobjectprivate 是**來的?既然是 private,那麼它肯定不會在公開的標頭檔案中。於是我們立刻想到到 qobject.cpp 或者是 qobject_p.h 中尋找。終於,我們在 qobject_p.h 中找到了這個類的宣告:

class

q_core_export qobjectprivate : 

public

qobjectdata     

這個類是繼承 qobjectdata 的!想想也是,因為我們說過,qobjectdata 是不能被例項化的,如果要使用,必須建立它的乙個子類。顯然,qobjectprivate 就扮演了這麼乙個角色了。不僅如此,我們還在這裡看到了熟悉的 q_declare_public 巨集。好在我們已經知道它的含義了。

在 qobject.cpp 中,我們看一下 qobject 的建構函式:

qobject::qobject(qobject *parent)  

: d_ptr(

newqobjectprivate)     

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

: d_ptr(&dd)     

第乙個建構函式就是我們經常見到的那個。它使用自己建立的 qobjectprivate 指針對 d_ptr 初始化。第二個建構函式使用傳入的 qobjectprivate 物件,但它是 protected 的,也就是說,你不能在外部類中使用這個建構函式。那麼這個建構函式有什麼用呢?我們來看一下 qwidget 的**:

class

qwidget : 

public

qobject, 

public

qpaintdevice  

qwidget 是 qobject 的子類,然後看它的建構函式:

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

: qobject(*

newqwidgetprivate, 0), qpaintdevice()  

qt_catch(...)      

}    

它呼叫了那個qobject 的 protected 建構函式,並且傳入乙個 qwidgetprivate !這個 qwidgetprivate 顯然繼承了 qobjectprivate。於是我們已經明白,為什麼 qwidget 中找不到 d_ptr 了,因為所有的 d_ptr 都已經在父類 qobject 中定義好了!嘗試展開一下 q_declare_private 巨集,你就能夠發現,它實際上把父類的 qobjectprivate 指標偷偷地轉換成了 qwidgetprivate 的指標。這個就是前面說的 qt 的設計思路。

本文出自 「豆子空間」 部落格,請務必保留此出處

Qt核心剖析 資訊隱藏

如果你閱讀了 qt 的源 你會看到一堆奇奇怪怪的巨集,例如 q d,q q。我們的qt原始碼之旅就從理解這些巨集說起。下面先看乙個c 的例子。class person person string name void setname string name int age void setage in...

Qt核心剖析 資訊隱藏 1

如果你閱讀了 qt 的源 你會看到一堆奇奇怪怪的巨集,例如 q d,q q。我們的qt原始碼之旅就從理解這些巨集說起。下面先看乙個c 的例子。class person person string name void setname string name int age void setage in...

Qt原始碼剖析 資訊隱藏 3

前面我們已經看到了怎樣使用標準的 c 以及 qt 提供的 api 來達到資訊隱藏這一目標。下面我們來看一下 qt 是如何實現的。還是以 qobject 的源 作為例子。先開啟 qobject.h,找到 qobjectdata 這個類的宣告。具體 如下所示 qobjectdata 然後在下面就可以找到...