生活随笔
收集整理的這篇文章主要介紹了
解读 Q_D, Q_Q 指针
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
? ? ?見(jiàn) qglog.h文件定義:???
??? #define Q_D(Class) Class##Private * const d = d_func()
??? #define Q_Q(Class) Class * const q = q_func()
??d指針是在主類中使用的,來(lái)獲取私有子類成員指針
??q指針是在私有數(shù)據(jù)類中使用的,來(lái)獲取主類對(duì)象指針
D-指針?
?? 私有成員總是不可見(jiàn)的,Qt中私有成員不僅僅是簡(jiǎn)單封裝一下,將訪問(wèn)權(quán)限改為private,它將所有私有數(shù)據(jù)封裝在私有類里(命名就是 classname##private), 這樣一來(lái)連用戶都不知道他到底封裝了什么,程序中只有這個(gè)私有類成員指針,這個(gè)指針就是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的構(gòu)造函數(shù)如下:???
?
[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的一個(gè)方法
?
?
[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 指針的代碼給封裝起來(lái)了,之后就可以直接使用d->
?
?
?
QObject的第二個(gè)構(gòu)造函數(shù)使用傳入的 QObjectPrivate 對(duì)象,但它是 protected 的,也就是說(shuō),你不能在外部類中使用這個(gè)構(gòu)造函數(shù)。那么這個(gè)構(gòu)造函數(shù)有什么用呢?我們來(lái)看一下 QWidget 的代碼:
?
[c-sharp]?view plain
?copy class?QWidget?:?public?QObject,?public?QPaintDevice??{??????Q_OBJECT??????Q_DECLARE_PRIVATE(QWidget)??????}?? ?
?
?
?
QWidget 是 QObject 的子類,然后看它的構(gòu)造函數(shù):
?
[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
于是我們已經(jīng)明白,為什么 QWidget 中找不到 d_ptr 了,因?yàn)樗械?d_ptr 都已經(jīng)在父類 QObject 中定義好了!嘗試展開一下 Q_DECLARE_PRIVATE 宏,你就能夠發(fā)現(xiàn),它實(shí)際上把父類的 QObjectPrivate 指針偷偷地轉(zhuǎn)換成了 QWidgetPrivate 的指針。
?
因此有如下結(jié)論:?
1、在基類中定義一個(gè)protected權(quán)限的基類私有類d_ptr指針;
2、在每個(gè)派生類中用本類私有類初始化d_ptr(該私有類需要繼承基類私有類),并定義d_func(),獲取基類d_ptr,這個(gè)d_func()是由?????Q_DECLARE_PRIVATE展開得來(lái)的?,并將其轉(zhuǎn)換為當(dāng)前私有類指針;
3、在函數(shù)中使用Q_D,這樣就可以使用d了;
4、在私有數(shù)據(jù)繼承體系中,不要忘記將析構(gòu)函數(shù)定義為虛函數(shù),基類析構(gòu)函數(shù)中釋放d_ptr,以防內(nèi)存泄露!!!
============================================================
Q-指針?
?? q指針是在私有數(shù)據(jù)類中使用的,來(lái)獲取主類指針。?
[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()???
三、使用的例子:
???? 在使用調(diào)色板中
[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();??}??
轉(zhuǎn)載于:https://www.cnblogs.com/senior-engineer/p/8065370.html
總結(jié)
以上是生活随笔為你收集整理的解读 Q_D, Q_Q 指针的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。