我一直在阅读一篇关于C ++接口(http://accu.org/index.php/journals/233)的文章,我完全迷失了它所说的所有虚拟成员函数应该被私有的部分(标题为“强化分离”的部分)。对我来说根本没有意义。
根据作者的说法,代码是这样的:
class shape {
public:
virtual ~shape();
virtual void move_x(distance x) = 0;
virtual void move_y(distance y) = 0;
virtual void rotate(angle rotation) = 0;
//...
};
class line : public shape {
public:
line(point end_point_1, point end_point_2);
//...
private:
virtual ~line();
virtual void move_x(distance x);
virtual void move_y(distance y);
virtual void rotate(angle rotation);
//...
};
所以我们有一个纯粹的虚函数,它是公共的,它的实现(在行类中)是私有的。
有人可以解释一下如何调用move_x函数吗?它的访问说明符是私有的,如果我尝试这样做会导致错误:
line my_line(point(0,0), point(1,2));
my_line.move_x(-1); // does not compile
同样,说绘图界面(参见本文前面部分)也无法访问这些函数是正确的吗?
谢谢。
答案 0 :(得分:6)
这个想法是你通过引用或指针shape
来使用这些方法。
shape &s = my_line;
s.move_x(-1);
这可以通过“仅揭示你需要的东西”或作为一种自我记录的形式来证明。它证明了这些方法只是按照预期的方式调用。
答案 1 :(得分:4)
如果你有line
对象的实例,你可能会想要调用它的方法。但是,如果你能够获得它们的唯一方法是通过询问它的shape
接口,那么该对象看起来不像一个对象,更像是一个接口集合。
如果您想象实现多个接口的行,这会更有意义。
答案 2 :(得分:3)
此建议仅适用于同类层次结构 - 也就是说,派生类不引入新函数(可能除了构造函数)并且只是覆盖基类函数的层次结构。在这种情况下,您显然不需要直接使用line
实例 - 只能通过指向shape
的引用。
如果你的层次结构不太一致,那么这个建议就没有多大意义了:当派生类引入新函数或从另一个基类继承它们时,如何将它应用于案例?在这种情况下,您有时希望直接使用派生类的对象,这种建议只会带来不便。
进一步发展这个想法 - 在更多情境中更少激进和可用 - Herb Sutter Non-Virtual Interface(NVI)。
答案 3 :(得分:2)
我认为这篇文章很好地突出了这句话的基本原理:
现在,用户可以做的唯一事情 line是创建它的实例。所有 用法必须通过其界面 - 即 形状,从而强化更强 接口/实现分离。 在离开这个主题之前,它是 得到一些直线的重要事项: 强制执行的要点 接口/实现分离是 不告诉用户该做什么。相反, 目标是巩固 逻辑分离 - 现在的代码 解释说,关键的抽象是 形状,并且该线用于提供 形状的实现。
也就是说,line
本身并不有趣。它只是shape
接口的一个实现,可能还有其他实现。您对shape
界面特别感兴趣。因此,您应该只通过此接口访问实现,而不是作为独立的类。