2

例如

// Implementation.
struct PrivatePoint {
  void SomePrivateMethod();

  double x;
  double y;
}

struct Point : private PrivatePoint {
  double DistanceTo(const Point& other) const;
}

这似乎类似于Pimpl 成语。这有两个我非常喜欢的优点:

  1. SomePrivateMethod 是可测试的。如果 SomePrivateMethod 在 Point 中被声明为私有,您将无法从测试中调用它。如果您在 Point 中将其声明为 public 或 protected,测试将能够调用它,但 Point 的普通用户也可以调用它。
  2. 与您在 Pimpl 惯用语中的操作相比,访问私有数据更容易读写,因为您不必通过指针,例如

.

Point::DistanceTo(const Point& other) {
  SomePrivateMethod();

  double dx = other.x - x;
  double dy = other.y - y;
  return sqrt(dx * dx + dy * dy);
}

对比

Point::DistanceTo(const Point& other) {
  ptr->SomePrivateMethod();

  double dx = other.ptr->x - ptr->x;
  double dy = other.ptr->y - ptr->y;
  return sqrt(dx * dx + dy * dy);
}
4

3 回答 3

2

你的建议有一些缺点......

用户可以将自己耦合到“私人”类。

pimpl idiom 的主要目的是作为编译防火墙,允许在实现文件中指定私有成员,因此可以在不触及标题和需要/触发客户端重新编译的情况下进行更改,这与重新链接不同,后者更快,并且如果更新是动态加载的库,甚至可能不需要涉及客户端应用程序的任何操作。你失去了这些好处。

SomePrivateMethod 是可测试的。如果 SomePrivateMethod 在 Point 中被声明为私有,您将无法从测试中调用它。如果您在 Point 中将其声明为 public 或 protected,测试将能够调用它,但 Point 的普通用户也可以调用它。

还有其他方便的选项:例如 - 您可以声明与测试代码的友谊,或使用预处理器构建暴露数据的测试模式。

于 2012-09-21T02:07:04.530 回答
1

私有继承与组合(和 pimpl)非常相似,但有一些缺点需要考虑:

  1. 您需要使 PrivatePoint 定义在公共标头中可见。这引入了对 PrivatePoint 的编译时间依赖性,并且每次 PrivatePoint 更改时都需要 Point 的客户端重新编译。对于 pimpl,情况并非如此,只需像这样转发声明 PrivatePoint: struct PrivatePoint;

  2. 封装是一周。通过私有继承,扩展 Point 的客户端能够实现自己的 SomePrivateMethod 版本(C++ 允许覆盖私有虚拟方法)。在您的示例中这不是问题,但如果 SomePrivateMethod 被声明为虚拟的

如果您使用 pimpl,您还可以轻松地对 PrivatePoint 进行单元测试。

于 2012-09-21T09:10:19.350 回答
0

no, as anyway you have to publish header file that declares the base class. the private inheritance protect you or your users from unwanted access to the data/methods.

于 2012-09-21T01:49:08.880 回答