首页 > Noshow > Inside Qt Series (四):对象数据存储(C)
15 2009-09

Inside Qt Series (四):对象数据存储(C)

接上节,让我们来看看这个 QObjectPrivate 和 QObject 是如何关联在一起的。

//--------------------------------
// file name: qobject.cpp
 
QObject::QObject(QObject *parent)
: d_ptr(new QObjectPrivate)
{
// ………………………
}
 
QObject::QObject(QObjectPrivate &dd, QObject *parent)
: d_ptr(&dd)
{
// …………………
}

怎么样,是不是一目了然呀?

从第一个构造函数可以很清楚的看出来,QObject class 中的 d_ptr 指针将指向一个 QObjectPrivate 的对象,而QObjectPrivate这个class是从QObjectData继承出来的。

这第二个构造函数干什么用的呢?从 QObject class 的定义中,我们可以看到,这第二个构造函数是被定义为 protected 类型的,这说明,这个构造函数只能被继承的class使用,而不能使用这个构造函数来直接构造一个QObject对象,也就是说,如果写一条下面的语句, 编译的时候是会失败的,

new QObject(*new QObjectPrivate, NULL)

为了看的更清楚,我们以QWidget这个class为例说明。

QWidget是QT中所有UI控件的基类,它直接从QObject继承而来,

class QWidget : public QObject, public QPaintDevice
{
Q_OBJECT
Q_DECLARE_PRIVATE(QWidget)
// .....................
}

我们看一个这个class的构造函数的代码:

QWidget::QWidget(QWidget *parent, Qt::WindowFlags f)
: QObject(*new QWidgetPrivate, 0), QPaintDevice()
{
d_func()->init(parent, f);
}

非常清楚,它调用了基类QObject的保护类型的构造函数,并且以 *new QWidgetPrivate 作为第一个参数传递进去。也就是说,基类(QObject)中的d_ptr指针将会指向一个QWidgetPrivate类型的对象。

再看QWidgetPrivate这个class的定义:

class QWidgetPrivate : public QObjectPrivate
{
Q_DECLARE_PUBLIC(QWidget)
// .....................
}

好了,这就把所有的事情都串联起来了。

关于QWidget构造函数中的唯一的语句 d_func()->init(parent, f) 我们注意到在class的定义中有这么一句话: Q_DECLARE_PRIVATE(QWidget)

我们前面讲过这个宏,当把这个宏展开之后,就是这样的:

inline QWidgetPrivate* d_func() { return reinterpret_cast<QWidgetPrivate *>(d_ptr); }
inline const QWidgetPrivate* d_func() const
{ return reinterpret_cast<const QWidgetPrivate *>(d_ptr); } \
friend class QWidgetPrivate;

很清楚,它就是把QObject中定义的d_ptr指针转换为QWidgetPrivate类型的指针。

小结:

要理解QT Kernel的code,就必须要知道QT中每一个Object内部的数据是如何保存的,而QT没有象我们平时写code一样,把所有的变量直接定义在类 中,所以,不搞清楚这个问题,我们就无法理解一个相应的class。其实,在QT4.4中的类成员数据的保存方法在本质是与QT2.x中的是一样的,就是 在class中定义一个成员数据的指针,指向成员数据集合对象(这里是一个QObjectData或者是其派生类)。初始化这个成员变量的办法是定义一个 保护类型的构造函数,然后在派生类的构造函数new 一个派生类的数据成员,并将这个新对象赋值给QObject的数据指针。在使用的时候,通过预先定义个宏里面的一个inline函数来把数据指针在安全类 型转换,就可以使用了。

====================================
声明:
《Inside Qt Series》专栏文章是Qt核心技术论坛(InsideQt.com)原创技术文章。
本系列专栏文章可随意转载,但必须保留本段声明和每一篇文章的原始地址。
作者保留版权,未经作者同意,不得用于任何商业用途

《Inside Qt Series》专栏文章总索引:
http://www.insideqt.com/bbs/viewthread.php?tid=9
本文原始地址:
http://www.insideqt.com/bbs/viewthread.php?tid=7

前一篇:Inside QT Series (三):对象数据存储(B)
http://www.insideqt.com/bbs/viewthread.php?tid=6
后一篇:Inside QT Series (五):元对象系统(Meta-Object System)
http://www.insideqt.com/bbs/viewthread.php?tid=10
====================================

Noshow ,

  1. 本文目前尚无任何评论.
  1. 本文目前尚无任何 trackbacks 和 pingbacks.