生活随笔
收集整理的這篇文章主要介紹了
解读 Q_D, Q_Q 指针
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
? ? ?見 qglog.h文件定義:???
??? #define Q_D(Class) Class##Private * const d = d_func()
??? #define Q_Q(Class) Class * const q = q_func()
??d指針是在主類中使用的,來獲取私有子類成員指針
??q指針是在私有數據類中使用的,來獲取主類對象指針
D-指針?
?? 私有成員總是不可見的,Qt中私有成員不僅僅是簡單封裝一下,將訪問權限改為private,它將所有私有數據封裝在私有類里(命名就是 classname##private), 這樣一來連用戶都不知道他到底封裝了什么,程序中只有這個私有類成員指針,這個指針就是D-指針。
從QObject開始看?
?
[c-sharp]?view plain
?copy class?QObject??{??????Q_DECLARE_PRIVATE(QObject)??public:??????Q_INVOKABLE?explicit?QObject(QObject?*parent=0);??protected:??????QObject(QObjectPrivate?&dd,?QObject?*parent?=?0);??????QScopedPointer<QObjectData>?d_ptr;??????}?? ?
?
?
?
展開后
?
[c-sharp]?view plain
?copy class?QObject??{??????????inline?QObjectPrivate*?d_func()?{?return?reinterpret_cast(qGetPtrHelper(d_ptr));?}??????inline?const?QObjectPrivate*?d_func()?const?{?return?reinterpret_cast(qGetPtrHelper(d_ptr));?}??????friend?class?QObjectPrivate;?????public:??????Q_INVOKABLE?explicit?QObject(QObject?*parent=0);??protected:??????QObject(QObjectPrivate?&dd,?QObject?*parent?=?0);??????QScopedPointer<QObjectData>?d_ptr;??????}?? ?
?
?
?
?
QObject的構造函數如下:???
?
[c-sharp]?view plain
?copy QObject::QObject(QObject?*parent)???????:?d_ptr(new?QObjectPrivate)??{????}??QObject::QObject(QObjectPrivate?&dd,?QObject?*parent)??????:?d_ptr(&dd)??{?????}?? ?
?
?
?
也就是QObjectData *d_ptr = new QObjectPrivate?
顯然QObjectPrivate 繼承了 QObjectData? ;
如下
?
[c-sharp]?view plain
?copy QObjectData?{??public:??????virtual?~QObjectData()?=?0;??????};?? ?
?
?
?
?
[c-sharp]?view plain
?copy class?Q_CORE_EXPORT?QObjectPrivate?:?public?QObjectData??{??????Q_DECLARE_PUBLIC(QObject)??public:??????QObjectPrivate(int?version?=?QObjectPrivateVersion);??????virtual?~QObjectPrivate();??????}?? ?
?
?
?
看看QObject的一個方法
?
?
[c-sharp]?view plain
?copy QString?QObject::objectName()?const??{??????Q_D(const?QObject);??????return?d->objectName;??}?? ?
?
?
展開后
?
[c-sharp]?view plain
?copy QString?QObject::objectName()?const??{??????QObjectPrivate?*?const?d?=?d_func()????????return?d->objectName;??}?? ?
?
?
所以Qt 為我們把從 d_func() 獲取 QObjectPrivate 指針的代碼給封裝起來了,之后就可以直接使用d->
?
?
?
QObject的第二個構造函數使用傳入的 QObjectPrivate 對象,但它是 protected 的,也就是說,你不能在外部類中使用這個構造函數。那么這個構造函數有什么用呢?我們來看一下 QWidget 的代碼:
?
[c-sharp]?view plain
?copy class?QWidget?:?public?QObject,?public?QPaintDevice??{??????Q_OBJECT??????Q_DECLARE_PRIVATE(QWidget)??????}?? ?
?
?
?
QWidget 是 QObject 的子類,然后看它的構造函數:
?
[c-sharp]?view plain
?copy QWidget::QWidget(QWidgetPrivate?&dd,?QWidget*?parent,?Qt::WindowFlags?f)??????:?QObject(dd,?0),?QPaintDevice()??{??????Q_D(QWidget);??????QT_TRY?{??????????d->init(parent,?f);??????}?QT_CATCH(...)?{??????????QWidgetExceptionCleaner::cleanup(this,?d_func());??????????QT_RETHROW;??????}??}?? ?
?
?
?
?
顯然了QWidgetPrivate 繼承了QObjectPrivate
于是我們已經明白,為什么 QWidget 中找不到 d_ptr 了,因為所有的 d_ptr 都已經在父類 QObject 中定義好了!嘗試展開一下 Q_DECLARE_PRIVATE 宏,你就能夠發現,它實際上把父類的 QObjectPrivate 指針偷偷地轉換成了 QWidgetPrivate 的指針。
?
因此有如下結論:?
1、在基類中定義一個protected權限的基類私有類d_ptr指針;
2、在每個派生類中用本類私有類初始化d_ptr(該私有類需要繼承基類私有類),并定義d_func(),獲取基類d_ptr,這個d_func()是由?????Q_DECLARE_PRIVATE展開得來的?,并將其轉換為當前私有類指針;
3、在函數中使用Q_D,這樣就可以使用d了;
4、在私有數據繼承體系中,不要忘記將析構函數定義為虛函數,基類析構函數中釋放d_ptr,以防內存泄露!!!
============================================================
Q-指針?
?? q指針是在私有數據類中使用的,來獲取主類指針。?
[cpp]?view plain
?copy class?Q_CORE_EXPORT?QObjectPrivate?:?public?QObjectData??{??????Q_DECLARE_PUBLIC(QObject)????public:?????????};?? 展開后:
[cpp]?view plain
?copy class?Q_CORE_EXPORT?QObjectPrivate?:?public?QObjectData??{??????inline?QObject*?q_func()?{?return?static_cast<QObject?*>(q_ptr);?}?/???????inline?const?QObject*?q_func()?const?{?return?static_cast<const?QObject?*>(q_ptr);?}?/???????friend?class?QObject;??????}?? ? QObjectData定義如下:
[cpp]?view plain
?copy QObjectData?{???????public:??????????QObject?*q_ptr;??????}??#define?Q_Q(QObject)?QObject?*?const?q?=?q_func()???
三、使用的例子:
???? 在使用調色板中
[cpp]?view plain
?copy void?QWidget::setPalette(const?QPalette?&palette)??{??????Q_D(QWidget);?????setAttribute(Qt::WA_SetPalette,?palette.resolve()?!=?0);?????????QPalette?naturalPalette?=?d->naturalWidgetPalette(d->inheritedPaletteResolveMask);??????QPalette?resolvedPalette?=?palette.resolve(naturalPalette);??????d->setPalette_helper(resolvedPalette);?}??void?QWidgetPrivate::setPalette_helper(const?QPalette?&palette)??{??????Q_Q(QWidget);??????if?(data.pal?==?palette?&&?data.pal.resolve()?==?palette.resolve())??????????return;??????data.pal?=?palette;??????updateSystemBackground();??????propagatePaletteChange();??????updateIsOpaque();??????q->update();??????updateIsOpaque();??}??
轉載于:https://www.cnblogs.com/senior-engineer/p/8065370.html
總結
以上是生活随笔為你收集整理的解读 Q_D, Q_Q 指针的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。