e.g。
// Implementation.
struct PrivatePoint {
void SomePrivateMethod();
double x;
double y;
}
struct Point : private PrivatePoint {
double DistanceTo(const Point& other) const;
}
这似乎与Pimpl idiom类似。这有两个我非常喜欢的优点:
Point::DistanceTo(const Point& other) {
SomePrivateMethod();
double dx = other.x - x;
double dy = other.y - y;
return sqrt(dx * dx + dy * dy);
}
VS
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);
}
答案 0 :(得分:2)
你的建议有一些缺点......
用户可以将自己联系到“私人”课程。
pimpl习惯用法的主要目的是作为编译防火墙,允许私有成员在实现文件中指定,因此可以在不触及标题的情况下进行更改,并且需要/触发客户端重新编译,这与仅重新链接不同,这是如果更新是动态加载的库,则更快,甚至可能不需要涉及客户端应用程序的任何操作。你失去了这些好处。
SomePrivateMethod是可测试的。如果SomePrivateMethod在Point中被声明为private,则无法从测试中调用它。如果你在Point中声明它是公共的或受保护的,那么测试就可以调用它,但Point的常规用户也是如此。
还有其他方便的hackish选项:例如 - 您可以使用测试代码声明友谊,或使用预处理器构建公开数据的测试模式。
答案 1 :(得分:1)
私有继承与组合(和pimpl)非常相似,但有一些缺点需要考虑:
您需要在公共标头中显示PrivatePoint定义。这引入了对PrivatePoint的编译时依赖性,并且每次更改PrivatePoint时都要求Point的客户端重新编译。对于pimpl,情况并非如此,只需转发声明PrivatePoint就可以了: struct PrivatePoint;
封装是周末的。通过私有继承,扩展Point的客户端能够实现自己的SomePrivateMethod版本(C ++允许覆盖私有虚方法)。这不是您的示例中的问题,但如果SomePrivateMethod被声明为虚拟
如果你使用了pimpl,你也可以轻松地对PrivatePoint进行单元测试。
答案 2 :(得分:0)
不,无论如何你必须发布声明基类的头文件。私有继承保护您或您的用户免受对数据/方法的不必要的访问。