Qt 4.4.x中的方法
在Qt 4.4中,類別成員變量定義方法的出發點沒有變化,只是在具體的實現手段上發生了非常大的變化,下面具體來看。
在Qt 4.4中,使用了非常多的巨集來做事,這憑空的增加了理解Qt source code的難度,不知道他們是不是從MFC學來的。 就連在定義類別成員數據變量這件事情上,也大量的使用了巨集。
在這個版本中,類別成員變量不再是給每一個class都定義一個私有的成員,而是把這一項common的工作放到了最基礎的基類別QObject中,然後定義了一些相關的方法來存取,好了,讓我們進入具體的代碼吧。
- 代碼: 選擇全部
//------------------------------------------------------
// file name: qobject.h
class QObjectData
{
public:
virtual ~QObjectData() = 0;
// 省略
};
class QObject
{
Q_DECLARE_PRIVATE(QObject)
public:
QObject(QObject *parent=0);
protected:
QObject(QObjectPrivate &dd, QObject *parent = 0);
QObjectData *d_ptr;
}
bjectData *d_ptr;定義成protected類別型的就是要讓所有的派生類別都可以存取這個變量,而在外部卻不可以直接存取這個變量。 而QObjectData的定義卻放在了這個頭文件中,其目的就是為了要所有從QObject繼承出來的類別的成員變量也都相應的要在QObjectData這個class繼承出來。 而純虛的析構函數又決定了兩件事:
*這個class不能直接被實例化。 換句話說就是,如果你寫了這麼一行代碼,new QObjectData,這行代碼一定會出錯,compile的時候是無法過關的。
*當delete這個指針變量的時候,這個指針變量是指向的任意從QObjectData繼承出來的對象的時候,這個對像都能被正確delete,而不會產生錯誤,諸如,內存洩漏之類別的。
我們再來看看這個巨集做了什麼, Q_DECLARE_PRIVATE(QObject)
- 代碼: 選擇全部
#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_func(),作用就是把在QObject這個class中定義的數據成員變量d_ptr安全的轉換成為每一個具體的class的數據成員類別型指針。 我們看一下在QObject這個class中,這個巨集展開之後的情況,就一幕了然了。
Q_DECLARE_PRIVATE(QObject)展開後,就是下面的代碼:
- 代碼: 選擇全部
inline QObjectPrivate* d_func() { return reinterpret_cast<QObjectPrivate *>(d_ptr); }
inline const QObjectPrivate* d_func() const
{ return reinterpret_cast<const QObjectPrivate *>(d_ptr); } \
friend class QObjectPrivate;
巨集展開之後,新的問題又來了,這個QObjectPrivate是從哪裡來的? 在QObject這個class中,為什麼不直接使用QObjectData來數據成員變量的類別型?
還記得我們剛才說過嗎,QObjectData這個class的析構函數的純虛函數,這就說明這個class是不能實例化的,所以,QObject這個class的成員變量的實際類別型,這是從QObjectData繼承出來的,它就是QObjectPrivate !
這個class中保存了許多非常重要而且有趣的東西,其中包括Qt最核心的signal和slot的數據,屬性數據,等等,我們將會在後面詳細講解,現在我們來看一下它的定義:
下面就是這個class的定義:
- 代碼: 選擇全部
class QObjectPrivate : public QObjectData
{
Q_DECLARE_PUBLIC(QObject)
public:
QObjectPrivate(int version = QObjectPrivateVersion);
virtual ~QObjectPrivate();
// 省略
}
那麼,這個QObjectPrivate和QObject是什麼關係呢? 他們是如何關聯在一起的呢?
====================================
聲明:
《Inside Qt Series》專欄文章是Qt核心技術論壇(InsideQt.com)原創技術文章。
本系列專欄文章可隨意轉載,但必須保留本段聲明和每一篇文章的原始地址。
作者保留版權,未經作者同意,不得用於任何商業用途
《Inside Qt Series》專欄文章總索引:
http://www.insideqt.com/bbs/viewthread.php?tid=9
本文原始地址:
http://www.insideqt.com/bbs/viewthread.php?tid=6
前一篇: Inside QT Series (二):對像數據存儲(A)
http://www.insideqt.com/bbs/viewthread.php?tid=5
後一篇: Inside QT Series (四):對像數據存儲(C)
http://www.insideqt.com/bbs/viewthread.php?tid=7
====================================