zoukankan      html  css  js  c++  java
  • Qt框架分析

    https://blog.csdn.net/dadan1314/article/details/82831341

    类结构

    先分析qt gui程序最常用的两个大类QApplication和QWidget的继承关系,如下:

    在分析QApplication和QWidget的构造过程,如下:

    结合继承关系和构造过程分析类结构:

    ① 以QObject为基类,QObject ◁﹣QCoreApplication ◁﹣QGuiApplication ◁﹣QApplication,QApplication到顶,QApplication  是派生类的最顶端,没有内部构造函数,其他都有一个内部构造和一个外部构造,外部构造直接通过外部参数来构造,内部构造需带一个QXXXPrivate类指针参数,这是我们通过继承关系和构造过程来分析出来的;

    ② QObjectData ◁﹣QObjectPrivate ◁﹣QCoreApplicationPrivate ◁﹣QGuiApplicationPrivate ◁﹣QApplicationPrivate,这是内部的一条非常重要的继承关系,当构造QXXXApplication时,都会先new一个QXXXApplicationPrivate对象,并通过它继承的基类内部构造函数先构造基类;

    所有第一个结论如下:

         继承于QObject类,QXXX必然聚合了一个继承于QObjectData的QXXXPrivate类,

    ③ 以QObject为基类QObject ◁﹣QWidget .....,从继承关系上分析类似于QXXXAplication,不同之处在于这条继承链没有顶端,用户可以自定义然后继续继承;

    ④ 从构造函数来分析,以QWidget为基类的QXXX类构造函数都多了一个QXXX*参数,其目的就是为了构成一个树形结构对象集合,根节点该参数为null,除了根节点,每个节点都有父QObject ,也可以有子QObject;区别于QXXXAplication是因为每个进程只允许有一个QXXXAplication对象;

    ⑤ 树形结构依赖QObjectData中定义的QObject *parent; QObjectList children;,如下:

    class Q_CORE_EXPORT QObjectData {
    public:
        virtual ~QObjectData() = 0;
        QObject *q_ptr;
        QObject *parent;
        QObjectList children;

        uint isWidget : 1;
        uint blockSig : 1;
        uint wasDeleted : 1;
        uint isDeletingChildren : 1;
        uint sendChildEvents : 1;
        uint receiveChildEvents : 1;
        uint isWindow : 1; //for QWindow
        uint unused : 25;
        int postedEvents;
        QDynamicMetaObjectData *metaObject;
        QMetaObject *dynamicMetaObject() const;
    };

     ⑥ 最终结论,如下:

    继承于QObject类的QXXX的类必然聚合了一个继承于QObjectData的QXXXPrivate类,QObject中d_ptr指向QXXXPrivate,QObjectData中q_ptr指向QXXX,parent存放父节点,children存放子节点;
    d指针和q指针

    原始d_ptr指针和q_ptr指针的定义,如下图:

    PS:d_ptr可以看成指向QObjectData类的智能指针

    实际使用d指针和p指针的定义,如下图:

    以QWidget为例:

    QScopedPointer<QObjectData> d_ptr; // d_ptr指向QWidgetPrivate基类智能指针

    QObject *q_ptr;                                      // q_ptr指向QWidget指针

    d_ptr = new QWidgetPrivate                 // 本质是这样的,但实际有附录源码参考

    q_ptr = new QWidget                            // 本质是这样的,但实际有附录源码参考

    QWidgetPrivate* d;                               // QWidget类方法中的局部变量

    QWidget* q;                                          // QWidgetPrivate类方法中的局部变量

    d_ptr到d的转换和q_ptr到q的转换,如下图:

     源代码中d_ptr与q_ptr赋值过程和d与q使用过程,如下:

    // QObject公开构造方法 qobject.cpp 814行
    QObject::QObject(QObject *parent)
        : d_ptr(new QObjectPrivate)
    {
        Q_D(QObject);
        d_ptr->q_ptr = this;
       
        ...
    }
    // QObject保护构造方法 qobject.cpp 839行
    QObject::QObject(QObjectPrivate &dd, QObject *parent)
        : d_ptr(&dd)
    {
        Q_D(QObject);
        d_ptr->q_ptr = this;
        
        ...
    }
    // QWidget公开构造方法 qwidget.cpp 1020行
    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保护构造方法 qwidget.cpp 1034行
    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;
        }
    }

    另外几个相关宏定义和模板函数,如下:

    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(); }

    #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_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()

    编译器

    moc(Meta-Object Compiler)

    uic(User Interface Compiler)

    rcc(Resource Compiler)

  • 相关阅读:
    sql执行顺序图
    solor5.4学习笔记
    linux 安装
    falsh,.swf文件修改z-index
    mysql 分区
    再次构架心得
    服务器,数据库连接注意mysql的user表
    数据库操作
    一知半见的load与get
    处理中文空格.replace((char)12288,' ')
  • 原文地址:https://www.cnblogs.com/Vancamel/p/11218019.html
Copyright © 2011-2022 走看看