• Qt框架浅析之二 ------ d指针


    https://blog.csdn.net/Moke_8453/article/details/54172587

    Qt中有很多如下的片段,d指针,一个Q_D宏声明接d->xxx。这个d指针从哪里来的,类成员变量里面没有,也没有其他很明显的地方。下面我主要来讲一下d指针的含义和好处。

     1 private:
     2    Q_DECLARE_PRIVATE(QRadioButton)
     3    Q_DISABLE_COPY(QRadioButton)
     4    friend class QAccessibleButton;
     5 
     6 QRadioButton::QRadioButton(QWidget *parent)
     7   : QAbstractButton(*new QRadioButtonPrivate, parent)
     8 {
     9     Q_D(QRadioButton);
    10     d->init();
    11 }

    下面这是和所有d指针相关的宏声明(位于global.h文件)

     1  template  static inline T *qGetPtrHelper(T *ptr) { return ptr; }
     2 
     3   #define Q_DECLARE_PRIVATE(Class) 
     4   inline Class##Private* d_func() { return reinterpret_cast<Class##Private *>(qGetPtrHelper(d_ptr)); } 
     5   inline const Class##Private* d_func() const { return reinterpret_cast<const Class##Private *>(qGetPtrHelper(d_ptr)); } 
     6   friend class Class##Private;
     7 
     8  #define Q_DECLARE_PRIVATE_D(Dptr, Class) 
     9  inline Class##Private* d_func() { return reinterpret_cast<Class##Private *>(Dptr); } 
    10  inline const Class##Private* d_func() const { return reinterpret_cast<const Class##Private *>(Dptr); } 
    11  friend class Class##Private;
    12 
    13  #define Q_DECLARE_PUBLIC(Class)                                   
    14  inline Class* q_func() { return static_cast >Class *<(q_ptr); } 
    15  inline const Class* q_func() const { return static_cast>const Class *<(q_ptr); } 
    16  friend class Class;
    17 
    18  #define Q_D(Class) Class##Private * const d = d_func()
    19  #define Q_Q(Class) Class * const q = q_func()

    先来解释一下这个d指针的意义,按照宏声明,他是声明了一个叫做QRadioButtonPrivate *d_func()的函数,然后用reinterpret_cast转换这个指针。至于这里在public和private声明时的reinterpret_cast和static_cast是因为:

        reinterpret_cast (expression)
        type-id必须是一个指针、引用、算术类型、函数指针或者成员指针。它可以把一个指针转换成一个整数,也可以把一个整数转换成一个指针(先把一个指针转换成一个整数,再把该整数转换成原类型的指针,还可以得到原先的指针值)。

        static_cast < type-id > (expression)
        该运算符把expression转换为type-id类型,但没有运行时类型检查来保证转换的安全性。
        ①用于类层次结构中基类(父类)和派生类(子类)之间指针或引用的转换。
        ②用于基本数据类型之间的转换,如把int转换成char,把int转换成enum。这种转换的安全性也要开发人员来保证。
        ③把空指针转换成目标类型的空指针。
        ④把任何类型的表达式转换成void类型。

        使用d指针的优点

        ①将具体实现和函数接口分离,解耦合,可以在不改动外部接口的情形下,对内部的实现做改动。
        ②可以很方便的实现跨平台,和①有关,只需要声明自己的private数据类,根据各个系统下自己去适配系统,然后加入各自的private类头文件即可。接口和实现无关,在各自的私有实现中实现共同的接口即可。

    1      #ifdef Q_OS_WIN 
    2 
    3         #include <qprocess_win.h> 
    4 
    5  #ifdef Q_OS_MAC 
    6 
    7         #include <qprocess_mac.h> 

    ③实现层数据封装,有利于二进制兼容性。在版本变动小的情况下,4.8.4的qt库完全可以和4.8.6的dll,互相兼容(小插曲:qt在5.2发版的时候打破了二进制兼容,所以5.2的dll和5.1互相是兼容不了的,至于各个版本之间的具体兼容性,这个楼主没全部测试过,不过小版本的情况下,的确是可以互换的,比如4.8.5到4.8.6)。

  • 相关阅读:
    route add提示: "SIOCADDRT: No such process
    linux下route命令--说的比较清楚!
    linux route命令的使用详解
    Linux命令学习手册-route命令
    workqueue --最清晰的讲解
    udhcpc命令
    Mutex, semaphore, spinlock的深度解析
    dev_alloc_skb(len+16) skb_reserve(skb,2) skb_put(skb,len)
    skb_reserve(skb,2)中的2的意义
    option和 usb-serial驱动基本区别
  • 原文地址:https://www.cnblogs.com/Vancamel/p/11346307.html
Copyright © 2020-2023  润新知