zoukankan      html  css  js  c++  java
  • Qt的封装性d指针和q指针

    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;

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

  • 相关阅读:
    套接字和域名系统DNS
    TCP滑动窗口控制流量的原理
    AngularJS 路由
    使用纯前端JavaScript 实现Excel IO
    Deferred在jQuery和Angular中的使用与简单实现
    深入理解函数声明和函数表达式(转)
    Visual Studio Code 智能提示文件
    JavaScript框架设计(四) 字符串选择器(选择器模块结束)
    JavaScript框架设计(三) push兼容性和选择器上下文
    canvas学习和面向对象(二)
  • 原文地址:https://www.cnblogs.com/Vancamel/p/11345970.html
Copyright © 2011-2022 走看看