[英]C++ Multiple Inheritance to Implement Polymorphism
在JSF C ++编码标准中 ,AV规则87显示了抽象基类的图和作为多重继承的实现。
该图试图显示什么?
在此示例中,私有/保护继承的目的是什么?
如何将实现创建为基类?
AV规则87的图表显示D1从impl继承; 这是否意味着与接口无关的其他实现?
AV规则87
层次结构应基于抽象类。 参见Stroustrup 2,12.5。
基本原理:基于抽象类的层次结构倾向于将设计重点放在产生干净的接口,将实现细节保留在接口之外,并最小化编译依赖性,同时允许替代实现共存。 有关示例,请参阅附录A中的AV规则87。
...
附录A-AV规则87
基于抽象类的层次结构是首选。 因此,在图顶部的层次结构比在图底部的层次结构更可取。
使用形状的经典多态示例:
5.我的实现方法如下吗? 这对我来说似乎不正确。 我担心,我错过了设计的目的。 传统上,我希望Right_Triangle从Triangle继承。
class Shape{}; // Interface
class Right_Triangle{}; // Impl
class Triangle : public Shape,
private Right_Triangle {}; // D1
直角三角形是三角形,因此继承是相反的。
在您的示例中,根据编码规则,Shape必须是抽象类。 因此shape只能声明纯虚函数,例如Print(),Load(),rotate(),...
要从另一个实现(形状层次结构旁边)继承,则不应使用公共继承。
您的示例大体上是正确的,并遵循了AV 87的精神。尽管您输入了错字,但实现和公共类应具有相同的“种类”(例如,两者都应为通用三角形) :
class IShape { ... };
class TriangleImpl { ... };
class Triangle : public IShape,
private TriangleImpl { ... };
声称直角三角形是三角形的图是错误的 ,并且是一种常见的误解。 直角三角形不是三角形,除非您明确限制对三角形的处理方式(例如,使其变为只读)。 三角形可以具有所需的任意边长。 从三角形继承的类必须仍然像三角形那样工作。 这就是所谓的Liskov替代原理 。
由于您不能在任何地方都使用RightTriangle
类,因此可以无限制地使用Triangle
类,使Triangle
作为具体类使用(您不能在三角形上设置边长)-因此,所示的继承层次结构只是不好的设计。
类层次结构的设计不一定遵循维恩图,也不应该遵循“日常真理”。 长期的软件工程实践表明,坚持使用LSP可获得合理的继承图。
是的,如果教科书没有提供满足LSP的具体设计,那说明“直角三角形就是三角形”的精神错乱是错误的 。 对于形状, Trilateral
和Quadrilateral
界面必须是只读的,并且特定的顶点或边设置方法只能在派生类中提供,因为它们遵循不同的限制。 派生的具体类需要一个平坦的层次结构( Square
不是Rectangle
-如果是Rectangle
,则可以为其设置两个不同的边长!)。 同样,就LSP而言, Square
不是Quadrilateral
,因为四边形可以任意放置顶点,等等。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.