Qt助手:Object
Qt源碼解析:
// Src/qtbase/src/corelib/kernel/qobject.h
class Q_CORE_EXPORT QObject
{
Q_OBJECT // 提供元對象指針
Q_DECLARE_PRIVATE(QObject) // 提供訪問QObjectPrivate對象的接口
public:
Q_INVOKABLE explicit QObject(QObject *parent=0);
virtual ~QObject();
protected:
QObject(QObjectPrivate &dd, QObject *parent = 0);// 受保護構造函數,對外部屏蔽QObjectPrivate
protected:
QScopedPointer<QObjectData> d_ptr; // QObjectPrivate指針
private:
Q_DISABLE_COPY(QObject) // 私有化拷貝構造和賦值函數
Q_PRIVATE_SLOT(d_func(), void _q_reregisterTimers(void *))
};
疑問1:QObjectPrivate的作用?
疑問2:拷貝構造和賦值函數的私有化的作用?
// Src/qtbase/src/corelib/kernel/qobject_p.h
class Q_CORE_EXPORT QObjectPrivate : public QObjectData
{
Q_DECLARE_PUBLIC(QObject) // 提供訪問QObject對象的接口
public:
QObjectPrivate(int version = QObjectPrivateVersion);
virtual ~QObjectPrivate();
public:
ExtraData *extraData; // extra data set by the user
QThreadData *threadData; // id of the thread that owns the object
};
// Src/qtbase/src/corelib/kernel/qobject.h
class Q_CORE_EXPORT QObjectData {
public:
virtual ~QObjectData() = 0; // 純虛析構,所有private數據類必須從此類派生
QObject *q_ptr; // 數據類對應的接口類指針
QObject *parent; // 父
QObjectList children; // 所有子
uint isWidget : 1; // 快速判斷是否從QWidget繼承,比metaObjectName、強制轉換快
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; //
};
// include/QtCore/qglobal.h
#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;
// Q_DECLARE_PRIVATE(QObject)展開
inline QObjectPrivate* d_func() { return reinterpret_cast<QObjectPrivate *>(qGetPtrHelper(d_ptr)); } \
inline const QObjectPrivate* d_func() const { return reinterpret_cast<const QObjectPrivate *>(qGetPtrHelper(d_ptr)); } \
friend class QObjectPrivate;
#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;
// Q_DECLARE_PUBLIC(QObject)展開
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;
疑問3:QObject、QObjectPrivate如何關聯?
疑問4:從QObject派生的類與其XXXPrivate類如何關聯?
分析1:
- QObject提供接口,QObjectPrivate存儲數據
- QObject對外暴露,QObjectPrivate對外隱藏
- QObjectPrivate變化不影響QObject,減少依賴,提高編譯速度
分析3:
- 通過構造函數完成QObject、QObjectPrivate的關聯
// Src/qtbase/src/corelib/kernel/qobject.cpp
QObject::QObject(QObject *parent)
: d_ptr(new QObjectPrivate)
{
Q_D(QObject);
d_ptr->q_ptr = this;
...
}
QObject::QObject(QObjectPrivate &dd, QObject *parent)
: d_ptr(&dd)
{
Q_D(QObject);
d_ptr->q_ptr = this;
...
}
分析4:
- 以QWidget爲例,通過受保護的構造函數完成關聯
// Src/qtbase/src/widgets/kernel/qwidget.cpp
QWidget::QWidget(QWidget *parent, Qt::WindowFlags f)
: QObject(*new QWidgetPrivate, 0), QPaintDevice()
{
d_func()->init(parent, f);
}
QWidget::QWidget(QWidgetPrivate &dd, QWidget* parent, Qt::WindowFlags f)
: QObject(dd, 0), QPaintDevice()
{
Q_D(QWidget);
d->init(parent, f);
}
分析3:
- 每個QObject都有一個ObjectName
- 每個QObject內部會信號、槽鏈接
- 每個QObject會有自定義的property
- 對於上述內容,拷貝構造、複製函數都不好處理,所以把這兩個函數私有化