Vancamel

千山鸟飞绝,万径人踪灭。 孤舟蓑笠翁,独钓寒江雪。

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

https://blog.csdn.net/Ghost_bai/article/details/79565373

d指针

Qt对于数据的封装算比较高明的了,其实原理就是把接口和实现分开,类似于如下结构:

    class A
    {
        class APrivate;
        APrivate *pData;
        
        public:
        A();
        ~A();
        ...
    }

这样,接口类A只负责描述希望调用者看到的,而真正的细节都在APrivate类中,当然这是我个人的理解,Qt的实现要复杂的多。
以QWidget为例

先看代码:

    QWidget::QWidget(QWidget *parent, Qt::WindowFlags f)
        : QObject(*new QWidgetPrivate, 0), QPaintDevice()
    {
        QT_TRY {
            d_func()->init(parent, f);
        } QT_CATCH(...) {
            QWidgetExceptionCleaner::cleanup(this, d_func());
            QT_RETHROW;
        }
    }

这个是QWidget的构造函数,接着往下看:

    /*!
        \internal
    */
    QObject::QObject(QObjectPrivate &dd, QObject *parent)
        : d_ptr(&dd)
    {
        Q_D(QObject);
        d_ptr->q_ptr = this;
        ...
    }

这个是QObject的构造函数,看到有个d_ptr,类型为QScopedPointer<QObjectData>,现在好像明白了什么,在QWidget的构造函数中new了一个QWidgetPrivate对象,然后保存到基类的d_ptr中。

这里有两个宏定义,可以获取当前类的d指针,就是Q_D,实现如下:

#define Q_D(Class) Class##Private * const d = d_func()

这里有个d_func(),这时什么?不急,在Q_D定义的上方,就有一个Q_DECLARE_PRIVATE定义:

    #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;

接着就是:

    template <typename T> static inline T *qGetPtrHelper(T *ptr) { return ptr; }
    template <typename Wrapper> static inline typename Wrapper::pointer qGetPtrHelper(const Wrapper &p) { return p.data(); }

现在应该明白了,Qt里面细节都放在了Class##Private的类中,也算是一种定好的命名格式。

Q_DECLARE_PRIVATE这个是在类声明的时候调用Q_DECLARE_PRIVATE(QWidget)。

只要在使用d指针之前,加上Q_D(QWidget);就可以了。
q指针

与d指针相反,q指针是给Class##Private类调用的,是获取接口类的指针,同样有一个Q_Q宏定义:

#define Q_Q(Class) Class * const q = q_func()

同样,需要在Class##Private类声明出,调用Q_DECLARE_PUBLIC:

    #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;

更多细节可还要继续研究。

 

posted on 2019-08-13 15:01  我醉欲眠  阅读(700)  评论(0编辑  收藏  举报