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

时间:2013-01-15 11:02:04

标签: c++ architecture design-patterns

class MyClassPrivate
{
//My members.
};    

//and then
class MyClass {
private:
 MyClassPrivate* const d;
};

使用这种'模式'的原因是什么?它是如何正确调用的?

3 个答案:

答案 0 :(得分:4)

这称为“实施指针”或“pimpl”。见http://en.wikibooks.org/wiki/C++_Programming/Idioms#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的其他用户不需要重新编译。还不需要公开任何必须包含在成员中的头文件,这样可以缩短编译时间。

答案 1 :(得分:3)

最常用的是Pimlp成语。

  

Pimpl习语描述了制作头文件的方法   不受变化的影响。你经常会听到“避免改变你的想法”这样的建议   公共界面!“所以你可以修改你的私人界面,但是如何   当头文件定义私有时,你能避免重新编译吗?   方法。这就是Pimpl的作用 - 减少编译时的损失   您的私人界面会更改[3]。

来自Here

优点:

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

    1. 为实施者做更多工作。
    2. 不适用于需要按子类访问的“受保护”成员。
    3. 读取代码有点困难,因为某些信息不再出现在头文件中。
    4. 由于指针间接,运行时性能略有下降,特别是如果函数调用是虚拟的(间接分支的分支预测通常很差)。
    5. 怎么做:

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

答案 2 :(得分:1)

当您想要将界面与iplementation分开时,可以将此用于PIMPL idiom

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

此外,如果您对数据的操作遵循相同的接口,您可以将数据封装在私有类中,使此类成为层次结构的一部分,并在运行时(或编译时)在不同的数据实现之间切换对于这个问题 :))。

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

您可以直接将多边形定义为Point类型列表,并将这些点存储在不同的容器(列表或向量)中。 Polygon类可以通过间接寻址来定义,其中多边形实际上是点列表的ID列表(我在谈论一般意义上的列表)。这样,您可以测试PolygonGeometry类的不同算法,并查看它们如何与differtn Polygon实现一起使用。

这背后有一个设计原则:首选组合继承。无论何时使用Composition,并且依赖于在运行时确定的类型,您将拥有私有属性指针。