使用包含类数据的PrivateClass的好处是什么?

What are benefits of using PrivateClass containing data of the Class?

本文关键字:是什么 PrivateClass 包含类 数据      更新时间:2023-10-16
class MyClassPrivate
{
//My members.
};    
//and then
class MyClass {
private:
 MyClassPrivate* const d;
};

使用这种"模式"的原因是什么?它的正确叫法是什么?

这被称为"指针实现"或"pimpl"。见http://en.wikibooks.org/wiki/C + + _Programming/成语# Pointer_To_Implementation_.28pImpl.29

当你使用这种模式时,你将向前声明实现类,并在其他地方声明主体,即:

// header
class MyClassPrivate;
class MyClass {
public:
  MyClass();
  ~MyClass();
private:
  MyClassPrivate* const d;
};
// cpp
class MyClassPrivate {
};
MyClass::MyClass() : d(new MyClassPrivate) {}
MyClass::~MyClass() { delete d; }

这样做的好处是MyClass的实现不会暴露给MyClass的其他用户。如果实现改变,MyClass的其他用户不需要重新编译。任何必须为成员包含的头文件也不需要公开,这样可以缩短编译时间。

使用最多的是Pimlp成语。

  • 为什么要使用"PIMPL"习惯用法?
  • <
  • Pimpl成语/gh>
  • Pimpl

Pimpl习语描述了一种制作头文件的方法不受变化影响的。你经常听到这样的建议:"避免改变你的公共接口!"所以你可以修改你的私有接口,但是如何当你的头文件定义了私有属性时,你能避免重新编译吗方法。这就是Pimpl做什么-减少编译损害时你的私有接口改变了[3].

从这里

:

好处:

  1. 更改类的私有成员变量不需要重新编译依赖它的类,从而使时间更快,并且减少了FragileBinaryInterfaceProblem。
  2. 头文件不需要#include在私有成员变量中"按值"使用的类,因此编译时间更快。
  3. 这有点像SmallTalk自动处理类的方式…更纯的封装。

缺点:

  1. 实现者还有更多的工作要做。
  2. 对于需要子类访问的"protected"成员不起作用。
  3. 有点难读代码,因为一些信息不再在头文件。
  4. 运行时的性能会因为指针的间接而受到轻微的影响,特别是如果函数调用是虚拟的(间接分支的分支预测通常很差)。

怎么做:

  1. 将所有私有成员变量放入一个结构体中。
  2. 将结构体定义放在。cpp文件中。
  3. 在头文件中,只放入结构体的ForwardDeclaration。
  4. 在类定义中,声明一个(智能)指针作为唯一的私有成员变量。
  5. 类的构造函数需要创建这个结构体。
  6. 类的析构函数需要销毁该结构(可能由于使用智能指针而隐式地销毁)。
  7. 赋值操作符和CopyConstructor需要适当地复制结构体,否则将被禁用。

当您希望将接口与实现分离时,您可以将其用于PIMPL习语。

许多设计模式也使用指向私有属性的"指针",例如策略模式。此模式允许您在运行时选择不同的算法。

同样,如果你让数据的操作遵循相同的接口,你可以将数据封装在一个Private Class中,使这个类成为层次结构的一部分,并在运行时(或编译时)在不同的数据实现之间切换。

一个很好的例子是保存多边形数据的几何类。每个多边形都提供对点的访问,您还可以删除多边形边缘并执行各种其他拓扑操作。如果你用deletePoint, addPoint, swapEdge等方法为Polygon类提供一个抽象基类,你可以测试不同的Polygon实现。

可以直接将多边形定义为Point类型的列表,并将这些点存储在不同的容器中(list或vector)。Polygon类可以通过间接寻址来定义,其中多边形实际上是点列表的id列表(我谈论的是一般意义上的列表)。这样,你就可以测试PolygonGeometry类的不同算法,看看它们是如何在不同的多边形实现中工作的。

这背后有一个设计原则:更喜欢组合而不是继承。当你使用Composition并且依赖于在运行时确定的类型时,你将拥有一个私有属性指针。