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