我对此链接中的概念存在误解。 http://wiki.qt.io/D-Pointer
在继承d-pointers进行优化的部分中, 在创建Label对象时,请说
Label::Label()
: Widget(*new LabelPrivate) // initialize the d-pointer with our own
Private
{
}
首先调用基础构造函数,然后调用派生的构造函数。由于派生的构造函数采用以下形式:
Widget::Widget(WidgetPrivate &d) : d_ptr(&d)
{
}
调用此基础构造函数。
WidgetPrivate *d_ptr
基类成员
*new LabelPrivate
的值为
class Widget
{
public:
Widget();
// ...
protected:
// only subclasses may access the below
// allow subclasses to initialize with their own concrete Private
Widget(WidgetPrivate &d);
WidgetPrivate *d_ptr;
};
我知道对象B可以访问受保护的成员d_ptr,它是一种WidgetPrivate *。我的问题是,可以使用此d_ptr访问LabelPrivate中的文本成员吗?
如果是,我担心的是为什么WidgetPrivate *类型中的d_ptr可以访问派生类成员文本?
如果不是,这是否意味着Label无法访问LabelPrivate中的成员文本,那么使用该模式的重点是什么?
为避免含糊不清,我在这里发布原始资料: widget.h
struct WidgetPrivate
{
WidgetPrivate(Widget *q) : q_ptr(q) { } // constructor that initializes
the q-ptr
Widget *q_ptr; // q-ptr that points to the API class
Rect geometry;
String stylesheet;
};
widget_p.h
Widget::Widget() : d_ptr(new WidgetPrivate(this))
{
}
Widget::Widget(WidgetPrivate &d) : d_ptr(&d)
{
}
widget.cpp
class Label : public Widget
{
public:
Label();
// ...
protected:
Label(LabelPrivate &d); // allow Label subclasses to pass on their Private
// notice how Label does not have a d_ptr! It just uses Widget's d_ptr.
};
label.h
#include "widget_p.h"
class LabelPrivate : public WidgetPrivate
{
public:
String text;
};
Label::Label()
: Widget(*new LabelPrivate) // initialize the d-pointer with our own Private
{
}
Label::Label(LabelPrivate &d) : Widget(d)
{
}
label.cpp
{{1}}
答案 0 :(得分:0)
对于Widget,d_ptr只是一个WidgetPrivate *。 Label必须将其强制转换回LabelPrivate *才能访问其内容。
如果您在您引用的页面上进一步阅读了一节,您将看到实际获取LabelPrivate内容的完整代码:
void Label::setText(const String &text)
{
LabelPrivate *d = static_cast<LabelPrivate*>(d_ptr); // cast to our private type
d->text = text;
}
然后该文档继续描述一些隐藏这种冗长的Qt宏,但实现仍然是相同的。
总结模式的含义:顶级类和PIMPL指针都是层次结构。 Widget(Label)的子类将PIMPL指针设置为WidgetPrivate(LabelPrivate)的子类。现在,Widget实现可以访问WidgetPrivate超类的任何部分,因为它是存储指针的协变类型(子类指针总是可以转换为其超类)。但是,它对子类LabelPrivate一无所知。
一旦您进入Label实现,您就可以将PIMPL指针重新转换回您知道的子类版本(LabelPrivate),并拥有对内容的完全访问权。