日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) >

解读 Q_D, Q_Q 指针

發(fā)布時(shí)間:2025/5/22 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 解读 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;??
  • ????//?others??
  • }??
  • ?

    ?

    ?

    ?

    展開后

    ?

    [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;??
  • ????//?others??
  • }??
  • ?

    ?

    ?

    ?

    ?

    QObject的構(gòu)造函數(shù)如下:???

    ?

    [c-sharp]?view plain?copy
  • QObject::QObject(QObject?*parent)???
  • ????:?d_ptr(new?QObjectPrivate)??
  • {??
  • ??//?others??
  • }??
  • QObject::QObject(QObjectPrivate?&dd,?QObject?*parent)??
  • ????:?d_ptr(&dd)??
  • {??
  • ???//?others??
  • }??
  • ?

    ?

    ?

    ?

    也就是QObjectData *d_ptr = new QObjectPrivate?

    顯然QObjectPrivate 繼承了 QObjectData? ;

    如下

    ?

    [c-sharp]?view plain?copy
  • QObjectData?{??
  • public:??
  • ????virtual?~QObjectData()?=?0;??
  • ????//?others??
  • };??
  • ?

    ?

    ?

    ?

    ?

    [c-sharp]?view plain?copy
  • class?Q_CORE_EXPORT?QObjectPrivate?:?public?QObjectData??
  • {??
  • ????Q_DECLARE_PUBLIC(QObject)??
  • public:??
  • ????QObjectPrivate(int?version?=?QObjectPrivateVersion);??
  • ????virtual?~QObjectPrivate();??
  • ????//?others??
  • }??
  • ?

    ?

    ?

    ?

    看看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)??
  • ????//?others??
  • }??
  • ?

    ?

    ?

    ?

    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:??
  • ???//others...?????
  • ????};??
  • 展開后:

    [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;???
  • ???//others??
  • }??
  • ? QObjectData定義如下:

    [cpp]?view plain?copy
  • QObjectData?{??
  • ?????public:??????
  • ????QObject?*q_ptr;??
  • ????//others??????
  • }??
  • #define?Q_Q(QObject)?QObject?*?const?q?=?q_func()???

  • 三、使用的例子:

    ???? 在使用調(diào)色板中

    [cpp]?view plain?copy
  • void?QWidget::setPalette(const?QPalette?&palette)??
  • {??
  • ????Q_D(QWidget);?//得到私有成員?QWidgetPrivate指針?d??
  • ????setAttribute(Qt::WA_SetPalette,?palette.resolve()?!=?0);?????
  • ????QPalette?naturalPalette?=?d->naturalWidgetPalette(d->inheritedPaletteResolveMask);??
  • ????QPalette?resolvedPalette?=?palette.resolve(naturalPalette);??
  • ????d->setPalette_helper(resolvedPalette);?//調(diào)用QWidgetPrivate::setPalette_helper()??
  • }??
  • 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();??//調(diào)用QWidget::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ò),歡迎將生活随笔推薦給好友。