在 JSF C++ Coding Standards 中,AV规则87显示了抽象基类图和作为多重继承的实现。
这张图试图显示什么?
在此示例中,私有/保护继承的目的是什么?
如何将实现创建为基类?
AV规则87中的图表显示D1继承自impl;这是一个与接口无关的不同实现吗?
AV规则87
层次结构应该基于抽象类。见Stroustrup 2, 12.5。
理由: 基于抽象类的层次结构倾向于将设计集中在生成干净的接口上,从而保持实现细节 接口,并在允许时最小化编译依赖性 共存的替代实现。请参阅附录A中的AV规则87 例如。
...
附录A - AV规则87
首选基于抽象类的层次结构。因此 图表顶部的层次结构优先于层次结构 在图的底部。
使用形状的经典多态性示例:
5。 我的实施是否会如下?这对我来说似乎不对。我担心,我错过了设计的目的。传统上我希望Right_Triangle继承三角形。
class Shape{}; // Interface
class Right_Triangle{}; // Impl
class Triangle : public Shape,
private Right_Triangle {}; // D1
答案 0 :(得分:2)
右三角是一个三角形,所以继承是另一种方式。
在您的示例中,Shape必须是根据编码规则的抽象类。因此shape只能声明纯虚函数,如Print(),Load(),rotate(),...
要继承自另一个实现(在形状层次结构旁边),不应使用公共继承。
答案 1 :(得分:2)
你的例子大多是正确的,并且坚持AV 87的精神。你已经犯了一个错字,实现和公共类应该是相同的“种类”(因此,两者都应该是一个通用的三角形,例如):
class IShape { ... };
class TriangleImpl { ... };
class Triangle : public IShape,
private TriangleImpl { ... };
声称右三角形是三角形的图表错误,以及一个常见的误解。直角三角形不是三角形,除非您明确限制使用三角形可以做的事情(例如,将其设为只读)。三角形可以具有您想要的任何边长。从三角形继承的类仍然必须像三角形一样。它被称为Liskov Substitution Principle。
由于无法在任何地方使用RightTriangle
类,因此可以使用Triangle
类,而不会使Triangle
作为具体类无用(您不能在三角形上设置边长) - 因此所显示的继承层次结构只是糟糕的设计。
类层次结构的设计不一定遵循维恩图,也不应遵循“日常事实”。长期的软件工程实践表明,当您坚持使用LSP时,可以获得合理的继承图。
是的,如果教科书没有提供满足LSP的具体设计,那么证明这种“直角三角形是三角形”的教科书是错误的。在形状的情况下,Trilateral
和Quadrilateral
接口必须是只读的,并且特定的顶点或边缘设置方法只能在派生类中提供,因为它们遵循不同的限制。派生的具体类需要一个平面层次结构(Square
不是Rectangle
- 如果是,你可以为它设置两个不同的边长!)。同样,就LSP而言,Square
不是Quadrilateral
,因为四边形可以有任意放置的顶点等。