一、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。