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

来源:互联网 发布:开淘宝店技巧 编辑:程序博客网 时间:2024/05/16 10:32

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

private:   Q_DECLARE_PRIVATE(QRadioButton)   Q_DISABLE_COPY(QRadioButton)   friend class QAccessibleButton;QRadioButton::QRadioButton(QWidget *parent)  : QAbstractButton(*new QRadioButtonPrivate, parent){    Q_D(QRadioButton);    d->init();}
    下面这是和所有d指针相关的宏声明(位于global.h文件)
  template  static inline T *qGetPtrHelper(T *ptr) { return ptr; }  #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_PRIVATE_D(Dptr, Class) \ inline Class##Private* d_func() { return reinterpret_cast<Class##Private *>(Dptr); } \ inline const Class##Private* d_func() const { return reinterpret_cast<const Class##Private *>(Dptr); } \ 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; #define Q_D(Class) Class##Private * const d = d_func() #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类头文件即可。接口和实现无关,在各自的私有实现中实现共同的接口即可。

         #ifdef Q_OS_WIN 
    #include <qprocess_win.h>
    #ifdef Q_OS_MAC
    #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)。

0 0
原创粉丝点击