现在的位置: 首页 > 综合 > 正文

QT中的数据指针

2017年12月16日 ⁄ 综合 ⁄ 共 2027字 ⁄ 字号 评论关闭

 在此中以QGLWidget为例作为一个说明:

在源码头文件中看到该类的声明部分,第二行就是

DECLARE_PRIVATE(QGLWidget)

这是一个宏的定义,展开以后是这个样子的:

#define Q_DECLARE_PRIVATE(Class) /
    inline Class##Private* d_func() { return reinterpret_cast<Class##Private *>(d_ptr); } /
    inline const Class##Private* d_func() const { return reinterpret_cast<const Class##Private *>(d_ptr); } /
    friend class Class##Private;

也就是说定义了一个内联函数去得到一个私有数据成员的指针,大家在这里会得到将d_ptr强制转换而来的一个指针。指针的类型为QGLWidgetPrivate(这里的##是将前后连接起来的,编译器所完成的工作,我这里是以QGLWidget为例的,所以是QGLWidgetPrivate数据),我在看这里的时候有个疑问是这个数据指针存在于哪里,什么时候被分配了内存空间的。

下面是我的解释:

我们在调用QGLWidget的构造函数时,会先调用基类即QWidget的构造函数,我们其实是这样调用的:

QGLWidget::QGLWidget(QWidget *parent, const QGLWidget* shareWidget, Qt::WindowFlags f)
    : QWidget(*(new QGLWidgetPrivate), parent, f | Qt::MSWindowsOwnDC)

大家看到这里在构造QWidget时,给数据成员分配了内存空间,而这个构造函数实际上是按下面定义的:

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

依此类推,我们有理由相信,这个数据指针最终指向的是QObject中所定义的一个指针d_ptr。另外,我们还可以看到,这些最后带有Private的类也是有继承关系的,这就解释了,在各个类中d_ptr是如何呈现自身的特性的。

另外还有一点就是QGLWidgetPrivate中的数据又是在何时被初始化的呢,是在一个init函数中被初始化的,其调用如下显示:

QGLWidget::QGLWidget(QWidget *parent, const QGLWidget* shareWidget, Qt::WindowFlags f)
    : QWidget(*(new QGLWidgetPrivate), parent, f | Qt::MSWindowsOwnDC)
{
    Q_D(QGLWidget);     //这里获得了数据指针(据前面的解释)
    setAttribute(Qt::WA_PaintOnScreen);
    setAttribute(Qt::WA_NoSystemBackground);
    setAutoFillBackground(true); // for compatibility
    d->init(new QGLContext(QGLFormat::defaultFormat(), this), shareWidget); //这里对其进行初始化
}

还有两点需要注意的是,两个宏:

#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;

这个宏被用于数据类中调用去得到其所对应的实体类(例如:QGLWidgetPrivate对应于QGLWidget)

#define Q_DECLARE_PRIVATE(Class) /
    inline Class##Private* d_func() { return reinterpret_cast<Class##Private *>(d_ptr); } /
    inline const Class##Private* d_func() const { return reinterpret_cast<const Class##Private *>(d_ptr); } /
    friend class Class##Private;

这个宏刚好与之前的宏相反,用于实体类用于得对应的数据类成员。

抱歉!评论已关闭.