以Qt5.6.0为例
先分析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_ptr指针和q_ptr指针的定义,如下图:
PS:d_ptr可以看成指向QObjectData类的智能指针
实际使用d指针和p指针的定义,如下图:
以QWidget为例:
QScopedPointer
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 static inline T *qGetPtrHelper(T *ptr) { return ptr; }
template 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(qGetPtrHelper(d_ptr)); } \
inline const Class##Private* d_func() const { return reinterpret_cast(qGetPtrHelper(d_ptr)); } \
friend class Class##Private;
#define Q_DECLARE_PUBLIC(Class) \
inline Class* q_func() { return static_cast(q_ptr); } \
inline const Class* q_func() const { return static_cast(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)