這兩個宏在Qt的源碼中隨處可見,重要性不言而喻。在 部落格的 Inside Qt Series 系列文章中,他用了3篇文章來講這個問題。 因爲 QObject 本身比較複雜,這兩個宏和一個複雜的東西攪和到一塊,還真是不好理解。不過幸好,這個兩個宏和QObject 沒有必然的聯繫。故接下來,忘記 QObject,看一個普通的C++的類 例子類 QtServiceController 定義: class QtServiceController
{
Q_DECLARE_PRIVATE(QtServiceController)
public:
QtServiceController(const QString &name);
//省略其他
private:
QtServiceControllerPrivate *d_ptr;
};
|
宏定義
宏定義在 QtGlobal(即qglobal.h)頭文件中:
#define Q_DECLARE_PRIVATE(Class) \
inline Class##Private* d_func() { return reinterpret_cast<Class##Private *>(qGetPtrHelper(d_ptr)); } \
inline const Class##Private* d_func() const { return reinterpret_cast<const Class##Private *>(qGetPtrHelper(d_ptr)); } \
friend class Class##Private;
#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;
這兩個宏在這看起來真蠻繞的,因爲這個例子太簡單了,兩個宏的威力發揮不出來。反正核心就是:
-
在 QtServiceController 中通過 d_func() 可以獲得 QtServiceControllerPrivate 的指針 d_ptr
-
在 QtServiceControllerPrivate 中通過 q_func() 可以獲得 QtServiceController 的指針 q_ptr
Q_D 與 Q_Q
這是另兩個Qt源碼中隨處可見的宏,那麼它們有什麼用呢?
#define Q_D(Class) Class##Private * const d = d_func() #define Q_Q(Class) Class * const q = q_func()
兩個宏展開後分別是對 d_func 和 q_func 兩個函數的調用,返回值分別賦值給 d 和 q 兩個指針變量。
於是:
-
在 QtServiceController 中的成員函數中,我們只需要添加 Q_D(QtServiceController) 宏,在該函數內就可以直接用 d 來指代 d_ptr
-
在 QtServiceControllerPrivate 中的成員函數中,我們只需要添加 Q_Q(QtServiceController)宏,在該函數內就可以直接用 q 來指代 q_ptr
d_ptr與q_ptr
繞這麼大圈,爲什麼不直接用 d_ptr 與 q_ptr 呢。在,在我們的例子中,確實可以直接用,而且會更直接更簡單。官方這麼用了,或許是爲了和其他類保持一致吧。
但在其他情況下,這麼做顯然是有意義的,因爲 d_ptr 與 d,q_ptr 與 q 的類型並不一致(比如QObject系列)。這也是爲何宏展開後有cast的原因