Qt类结构分析

简介: Qt类结构分析

一、QObject

我们知道Qt中大部分类继承自QObject,并且其私有数据放在xxPrivate类中。例如:QObject的私有数据在QObjectPrivate中。

我们先来看下QObject类:

class Q_CORE_EXPORT QObject
{
    Q_OBJECT
    Q_PROPERTY(QString objectName READ objectName WRITE setObjectName NOTIFY objectNameChanged)
    Q_DECLARE_PRIVATE(QObject)
public:
    Q_INVOKABLE explicit QObject(QObject *parent=Q_NULLPTR);
    virtual ~QObject();
 
    ... ...
 
protected:
    QScopedPointer<QObjectData> d_ptr;
 
    ... ...
 
};

Q_OBJECT的宏定义如下:

#define Q_OBJECT \
public: \
    QT_WARNING_PUSH \
    Q_OBJECT_NO_OVERRIDE_WARNING \
    static const QMetaObject staticMetaObject; \
    virtual const QMetaObject *metaObject() const; \
    virtual void *qt_metacast(const char *); \
    virtual int qt_metacall(QMetaObject::Call, int, void **); \
    QT_TR_FUNCTIONS \
private: \
    Q_OBJECT_NO_ATTRIBUTES_WARNING \
    Q_DECL_HIDDEN_STATIC_METACALL static void qt_static_metacall(QObject *, QMetaObject::Call, int, void **); \
    QT_WARNING_POP \
    struct QPrivateSignal {}; \
    QT_ANNOTATE_CLASS(qt_qobject, "")

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;

对宏展开后为:

class Q_CORE_EXPORT QObject
{
    static const QMetaObject staticMetaObject;
    virtual const QMetaObject *metaObject() const;
    virtual void *qt_metacast(const char *);
    virtual int qt_metacall(QMetaObject::Call, int, void **);
    static void qt_static_metacall(QObject *, QMetaObject::Call, int, void **);
 
    Q_PROPERTY(QString objectName READ objectName WRITE setObjectName NOTIFY objectNameChanged)
    
    inline QObjectPrivate* d_func() { return reinterpret_cast<QObjectPrivate *>(d_ptr.data()); }
    inline const QObjectPrivate* d_func() const { return reinterpret_cast<const QObjectPrivate *>(d_ptr.data()); }
    friend class QObjectPrivate;
 
public:
    Q_INVOKABLE explicit QObject(QObject *parent=Q_NULLPTR);
    virtual ~QObject();
 
    ... ...
 
protected:
    QScopedPointer<QObjectData> d_ptr;
 
    ... ...
 
};

编译时,moc会产生metaObject(),qt_metacast(const char *),qt_metacall(QMetaObject::Call, int, void **),qt_static_metacall(QObject *, QMetaObject::Call, int, void **) 等这些函数的实现。

d_ptr这个成员变量,位于QObject中,即d_func()指向的就是其私有数据。

 

二、QObjectPrivate

class Q_CORE_EXPORT QObjectPrivate : public QObjectData
{
    Q_DECLARE_PUBLIC(QObject)
 
public:
    typedef void (*StaticMetaCallFunction)(QObject *, QMetaObject::Call, int, void **);
 
    QObjectPrivate(int version = QObjectPrivateVersion);
    virtual ~QObjectPrivate();
    void deleteChildren();
 
    void setParent_helper(QObject *);
    void moveToThread_helper();
    void setThreadData_helper(QThreadData *currentData, QThreadData *targetData);
    void _q_reregisterTimers(void *pointer);
 
    bool isSender(const QObject *receiver, const char *signal) const;
    QObjectList receiverList(const char *signal) const;
    QObjectList senderList() const;
 
    void addConnection(int signal, Connection *c);
    void cleanConnectionLists();
 
    static inline Sender *setCurrentSender(QObject *receiver,
                                    Sender *sender);
    static inline void resetCurrentSender(QObject *receiver,
                                   Sender *currentSender,
                                   Sender *previousSender);
 
    static QObjectPrivate *get(QObject *o) {
        return o->d_func();
    }
    static const QObjectPrivate *get(const QObject *o) { return o->d_func(); }
 
    int signalIndex(const char *signalName, const QMetaObject **meta = 0) const;
    inline bool isSignalConnected(uint signalIdx, bool checkDeclarative = true) const;
    inline bool isDeclarativeSignalConnected(uint signalIdx) const;
 
    // To allow abitrary objects to call connectNotify()/disconnectNotify() without making
    // the API public in QObject. This is used by QQmlNotifierEndpoint.
    inline void connectNotify(const QMetaMethod &signal);
    inline void disconnectNotify(const QMetaMethod &signal);
 
    template <typename Func1, typename Func2>
    static inline QMetaObject::Connection connect(const typename QtPrivate::FunctionPointer<Func1>::Object *sender, Func1 signal,
                                                  const typename QtPrivate::FunctionPointer<Func2>::Object *receiverPrivate, Func2 slot,
                                                  Qt::ConnectionType type = Qt::AutoConnection);
 
    template <typename Func1, typename Func2>
    static inline bool disconnect(const typename QtPrivate::FunctionPointer<Func1>::Object *sender, Func1 signal,
                                  const typename QtPrivate::FunctionPointer<Func2>::Object *receiverPrivate, Func2 slot);
 
    static QMetaObject::Connection connectImpl(const QObject *sender, int signal_index,
                                               const QObject *receiver, void **slot,
                                               QtPrivate::QSlotObjectBase *slotObj, Qt::ConnectionType type,
                                               const int *types, const QMetaObject *senderMetaObject);
    static QMetaObject::Connection connect(const QObject *sender, int signal_index, QtPrivate::QSlotObjectBase *slotObj, Qt::ConnectionType type);
    static bool disconnect(const QObject *sender, int signal_index, void **slot);
public:
    ExtraData *extraData;    // extra data set by the user
    QThreadData *threadData; // id of the thread that owns the object
 
    QObjectConnectionListVector *connectionLists;
 
    Connection *senders;     // linked list of connections connected to this object
    Sender *currentSender;   // object currently activating the object
    mutable quint32 connectedSignals[2];
 
    // these objects are all used to indicate that a QObject was deleted
    // plus QPointer, which keeps a separate list
    QAtomicPointer<QtSharedPointer::ExternalRefCountData> sharedRefcount;
};

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;


对其展开则为:

class Q_CORE_EXPORT QObjectPrivate : public QObjectData
{
    inline QObject* q_func() { return static_cast<QObject*>(q_ptr); } 
    inline const QObject* q_func() const { return static_cast<const QObject*>(q_ptr); }
    friend class QObject;
 
public:
    typedef void (*StaticMetaCallFunction)(QObject *, QMetaObject::Call, int, void **);
 
    ... ...
};

其中q_ptr位于QObjectData类中,QObject *q_ptr;

2.1 QObjectData

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 deleteLaterCalled : 1;
    uint unused : 24;
    int postedEvents;
    QDynamicMetaObjectData *metaObject;
    QMetaObject *dynamicMetaObject() const;
};

2.2 ExtraData

    struct ExtraData
    {
        ExtraData() {}
    #ifndef QT_NO_USERDATA
        QVector<QObjectUserData *> userData;
    #endif
        QList<QByteArray> propertyNames;
        QVector<QVariant> propertyValues;
        QVector<int> runningTimers;
        QList<QPointer<QObject> > eventFilters;
        QString objectName;
    };

2.3 Connection

    struct Connection
    {
        QObject *sender;
        QObject *receiver;
        union {
            StaticMetaCallFunction callFunction;
            QtPrivate::QSlotObjectBase *slotObj;
        };
        // The next pointer for the singly-linked ConnectionList
        Connection *nextConnectionList;
        //senders linked list
        Connection *next;
        Connection **prev;
        QAtomicPointer<const int> argumentTypes;
        QAtomicInt ref_;
        ushort method_offset;
        ushort method_relative;
        uint signal_index : 27; // In signal range (see QObjectPrivate::signalIndex())
        ushort connectionType : 3; // 0 == auto, 1 == direct, 2 == queued, 4 == blocking
        ushort isSlotObject : 1;
        ushort ownArgumentTypes : 1;
        Connection() : nextConnectionList(0), ref_(2), ownArgumentTypes(true) {
            //ref_ is 2 for the use in the internal lists, and for the use in QMetaObject::Connection
        }
        ~Connection();
        int method() const { Q_ASSERT(!isSlotObject); return method_offset + method_relative; }
        void ref() { ref_.ref(); }
        void deref() {
            if (!ref_.deref()) {
                Q_ASSERT(!receiver);
                delete this;
            }
        }
    };

2.4 ConnectionList

    struct ConnectionList {
        ConnectionList() : first(0), last(0) {}
        Connection *first;
        Connection *last;
    };

2.5 Sender

    struct Sender
    {
        QObject *sender;
        int signal;
        int ref;
    };

三、QWidget

class QWidget : public QObject, public QPaintDevice
{
    Q_OBJECT
    Q_DECLARE_PRIVATE(QWidget)
 
    explicit QWidget(QWidget* parent = Q_NULLPTR, Qt::WindowFlags f = Qt::WindowFlags());
    ~QWidget();
 
    ... ...
 
    QWidgetData *data;
}
 
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;
    }
}

展开:

class QWidget : public QObject, public QPaintDevice
{
    static const QMetaObject staticMetaObject;
    virtual const QMetaObject *metaObject() const;
    virtual void *qt_metacast(const char *);
    virtual int qt_metacall(QMetaObject::Call, int, void **);
    static void qt_static_metacall(QObject *, QMetaObject::Call, int, void **);
 
    
    inline QWidgetPrivate* d_func() { return reinterpret_cast<QWidgetPrivate *>(d_ptr.data()); }
    inline const QWidgetPrivate* d_func() const { return reinterpret_cast<const QWidgetPrivate *>(d_ptr.data()); }
    friend class QWidgetPrivate;
 
    explicit QWidget(QWidget* parent = Q_NULLPTR, Qt::WindowFlags f = Qt::WindowFlags());
    ~QWidget();
 
    ... ...
 
    QWidgetData *data;
}
 
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;
    }
}

四、QWidgetPrivate

class QWidgetPrivate : public QObjectPrivate {
    Q_DECLARE_PUBLIC(QWidget)
 
public:
    explicit QWidgetPrivate(int version = QObjectPrivateVersion);
    ~QWidgetPrivate();
 
    void init(QWidget *desktopWidget, Qt::WindowFlags f);
 
    ... ...
    
    QWExtra *extra;
    QWidget *focus_next;
    QWidget *focus_prev;
    QWidget *focus_child;
    QLayout *layout;
    QRegion *needsFlush;
    QPaintDevice *redirectDev;
    QWidgetItemV2 *widgetItem;
    QPaintEngine *extraPaintEngine;
    mutable const QMetaObject *polished;
    QGraphicsEffect *graphicsEffect;
// All widgets are added into the allWidgets set. Once
// they receive a window id they are also added to the mapper.
// This should just ensure that all widgets are deleted by QApplication
    static QWidgetMapper *mapper;
    static QWidgetSet *allWidgets;
 
    ... ...
    
};

展开:

class QWidgetPrivate : public QObjectPrivate {
    inline QWidget* q_func() { return static_cast<QWidget*>(q_ptr); } 
    inline const QWidget* q_func() const { return static_cast<const QWidget*>(q_ptr); }
    friend class QWidget;
 
public:
    explicit QWidgetPrivate(int version = QObjectPrivateVersion);
    ~QWidgetPrivate();
 
    ... ...
    
    QWExtra *extra;
    QWidget *focus_next;
    QWidget *focus_prev;
    QWidget *focus_child;
    QLayout *layout;
    QRegion *needsFlush;
    QPaintDevice *redirectDev;
    QWidgetItemV2 *widgetItem;
    QPaintEngine *extraPaintEngine;
    mutable const QMetaObject *polished;
    QGraphicsEffect *graphicsEffect;
// All widgets are added into the allWidgets set. Once
// they receive a window id they are also added to the mapper.
// This should just ensure that all widgets are deleted by QApplication
    static QWidgetMapper *mapper;
    static QWidgetSet *allWidgets;
 
    ... ...
    
};

五、QMainWindow

class Q_WIDGETS_EXPORT QMainWindow : public QWidget
{
    Q_OBJECT
 
    explicit QMainWindow(QWidget *parent = Q_NULLPTR, Qt::WindowFlags flags = Qt::WindowFlags());
    ~QMainWindow();
 
}
 
QMainWindow::QMainWindow(QWidget *parent, Qt::WindowFlags flags)
    : QWidget(*(new QMainWindowPrivate()), parent, flags | Qt::Window)
{
    d_func()->init();
}

六、QMainWindowPrivate

class QMainWindowPrivate : public QWidgetPrivate
{
    Q_DECLARE_PUBLIC(QMainWindow)
 
    
    void init();
 
}

七、总结

从上可以看到,qt大部分类都继承QObject,其私有数据则放在xxPrivate中,而xxPrivate都继承QObjectPrivate。备注QObjectPrivate继承QObjectData。


目录
相关文章
|
13天前
|
设计模式 前端开发 安全
Qt注册类对象单例与单类型区别
在进行开发时,应当根据具体的应用场景和需求来选择使用单例模式或是单类型。如果是全局服务或状态管理,可能需要单例模式;如果是为了使QML环境下的不同组件能够访问到同一个后端服务对象,则可能需要使用单类型。
16 2
|
1月前
|
编解码 开发框架
【Qt 学习笔记】Qt窗口 | Qt窗口介绍 | QMainwindow类及各组件介绍
【Qt 学习笔记】Qt窗口 | Qt窗口介绍 | QMainwindow类及各组件介绍
102 3
|
1月前
|
容器
【Qt 学习笔记】Qt常用控件 | 容器类控件 | Group Box的使用及说明
【Qt 学习笔记】Qt常用控件 | 容器类控件 | Group Box的使用及说明
83 3
|
1月前
|
容器
【Qt 学习笔记】Qt常用控件 | 容器类控件 | Tab Widget的使用及说明
【Qt 学习笔记】Qt常用控件 | 容器类控件 | Tab Widget的使用及说明
19 2
|
1月前
【Qt 学习笔记】Qt常用控件 | 输入类控件 | Slider的使用及说明
【Qt 学习笔记】Qt常用控件 | 输入类控件 | Slider的使用及说明
117 2
|
1月前
【Qt 学习笔记】Qt常用控件 | 输入类控件 | Dial的使用及说明
【Qt 学习笔记】Qt常用控件 | 输入类控件 | Dial的使用及说明
39 2
|
1月前
|
数据可视化
【Qt 学习笔记】Qt常用控件 | 输入类控件 | Date/Time Edit的使用及说明
【Qt 学习笔记】Qt常用控件 | 输入类控件 | Date/Time Edit的使用及说明
146 2
|
19天前
从源码角度分析Qt元对象系统2
从源码角度分析Qt元对象系统
39 0
|
19天前
|
存储
从源码角度分析Qt元对象系统1
从源码角度分析Qt元对象系统
45 0
|
1月前
【Qt 学习笔记】Qt常用控件 | 输入类控件 | Spin Box的使用及说明
【Qt 学习笔记】Qt常用控件 | 输入类控件 | Spin Box的使用及说明
86 0

推荐镜像

更多