C++ D-pointer/pimpl模式基类指针访问派生类成员
我对这个环节的概念有误解C++ D-pointer/pimpl模式基类指针访问派生类成员,c++,qt,C++,Qt,我对这个环节的概念有误解 在继承用于优化的d指针一节中, 创建标签对象时,例如 Label B; 首先调用基构造函数,然后调用派生构造函数。由于派生构造函数采用这种形式: Label::Label() : Widget(*new LabelPrivate) // initialize the d-pointer with our own Private { } 这个基本构造函数被调用 Widget::Widget(WidgetPrivate &d) : d_ptr(&d)
在继承用于优化的d指针一节中, 创建标签对象时,例如
Label B;
首先调用基构造函数,然后调用派生构造函数。由于派生构造函数采用这种形式:
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
我知道对象B可以访问WidgetPrivate*类型中的受保护成员d_ptr。我的问题是,是否可以使用此d_ptr访问LabelPrivate中的文本成员
如果是,我关心的是为什么WidgetPrivate*类型的d_ptr可以访问派生类成员文本
如果否,这是否意味着Label无法访问LabelPrivate中的成员文本,那么使用该模式有什么意义
为了避免歧义,我将原始材料张贴在此处: widget.h 小工具p.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.cpp
Widget::Widget() : d_ptr(new WidgetPrivate(this))
{
}
Widget::Widget(WidgetPrivate &d) : d_ptr(&d)
{
}
标签.h
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.cpp
#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)
{
}
对于小部件,d_ptr只是一个WidgetPrivate*。标签必须将其转换回LabelPrivate*才能访问其内容 如果您阅读所引用页面下方的一节,您将看到实际获取LabelPrivate内容的完整代码:
void Label::setText(const String &text)
{
LabelPrivate *d = static_cast<LabelPrivate*>(d_ptr); // cast to our private type
d->text = text;
}
void标签::setText(常量字符串和文本)
{
LabelPrivate*d=static_cast(d_ptr);//转换为我们的私有类型
d->text=文本;
}
然后,文档继续描述一些隐藏这种详细信息的Qt宏,但实现仍然是一样的
总结该模式的含义:顶级类和PIMPL指针都是层次结构。Widget(Label)的子类将PIMPL指针设置为WidgetPrivate(LabelPrivate)的子类。现在,小部件实现可以访问WidgetPrivate超类的任何部分,因为这是存储指针的协变类型(子类指针始终可强制转换到其超类)。但是,它对LabelPrivate子类一无所知
一旦进入标签实现,就可以将PIMPL指针重新转换回子类版本(LabelPrivate),并且可以完全访问其中的内容。看起来d-pointer是PIMPL习惯用法实现的另一个名称。这里的
LabelPrivate
并不意味着它有私有成员,而是它是Label
的“私有”细节。这就是我收集的…明白了。LabelPrivate是Label细节的一个实现。我的问题是,当LabelPrivate是WidgetPrivate的派生类时,为什么WidgetPrivate*ptr可以访问LabelPrivate的成员。这里没有给出LabelPrivate
和WidgetPrivate
的定义。我想小部件至少有两个构造函数。我们不需要参数,而是使用new WidgetPrivate()
初始化d\u ptr
。另一个接受一个WidgetPrivate&
参数并初始化d_ptr
,如图所示。对于小部件,d_ptr只是一个WidgetPrivate*。标签必须将其强制转换回LabelPrivate*才能访问其内容。因此,我可以说标签可以通过将WidgetPrivate*d_ptr强制转换为LabelPrivate*来访问LabelPrivate的文本成员吗?
void Label::setText(const String &text)
{
LabelPrivate *d = static_cast<LabelPrivate*>(d_ptr); // cast to our private type
d->text = text;
}