代码之家  ›  专栏  ›  技术社区  ›  Jerunh

C++多重继承实现多态性

  •  2
  • Jerunh  · 技术社区  · 10 年前

    JSF C++ Coding Standards ,AV规则87显示了抽象基类和作为多重继承的实现的图。

    1. 这个图表试图显示什么?

    2. 在本例中,Private/Protect继承的目的是什么?

    3. 如何将实现创建为基类?

    4. 来自AV规则87的图表显示D1继承自impl;这个impl是一个与接口无关的不同实现吗?

    AV规则87

    层次结构应该基于抽象类。参见Stroustrup 2, 12.5.

    理论基础: 基于抽象类的层次结构倾向于将设计重点放在生成干净的接口上,避免实现细节 接口,并最小化编译依赖性,同时允许 替代实现共存。见附录A中的AV规则87 例如。

    ...

    附录A-AV规则87

    首选基于抽象类的层次结构。因此 图表顶部的层次结构优先于层次结构 在图的底部。 JSF AV Rule 87

    使用形状的经典多态性示例:

    Classic Shapes Polymorphism example

    5. 我的实现是否如下?这对我来说似乎不正确。我担心,我错过了设计的目的。传统上,我希望Right_Triangle继承自Triangle。

     class Shape{};                              // Interface
     class Right_Triangle{};                     // Impl    
     class Triangle : public Shape,
                      private Right_Triangle {}; // D1
    
    2 回复  |  直到 10 年前
        1
  •  2
  •   Jerunh    10 年前

    你的例子基本上是正确的,并且符合AV 87的精神。虽然您犯了一个错误,但实现和公共类应该是相同的“类型”(例如,两者都应该是一个通用三角形):

    class IShape { ... };      
    class TriangleImpl { ... }; 
    class Triangle : public IShape,
                     private TriangleImpl { ... };
    

    声称直角三角形 是一个 三角形是 错误的 和一个常见的误解。直角三角形不是三角形,除非你明确限制你可以对三角形做什么(例如,让它只读)。三角形可以有你想要的任何边长。从三角形继承的类仍然必须*像三角形那样操作。它被称为 Liskov Substitution Principle .

    自从你 不能 使用 RightTriangle 到处上课a Triangle 类可以无限制地使用 三角形 作为一个具体的类是无用的(不能在三角形上设置边长度)-因此,所示的继承层次结构是一个糟糕的设计。

    这个 类层次结构的设计 不一定遵循维恩图,也不应该遵循“日常真理”。长期的软件工程实践表明,当您坚持LSP时,可以获得合理的继承图。

    是的,教科书证明了这种“直角三角形是三角形”的疯狂 都错了 如果他们不能提供满足LSP的具体设计。对于形状 Trilateral Quadrilateral 接口必须是只读的,并且特定的顶点或边缘设置方法只能在派生类中提供,因为它们遵循不同的限制。派生的具体类需要一个平面层次结构(a Square 不是 Rectangle -如果是,您可以为其设置两个不同的边缘长度!)。同样,就LSP而言 广场 不是 四边形的 ,因为四边形可以具有任意放置的顶点等。

        2
  •  2
  •   stefaanv    10 年前

    直角三角形是三角形,因此继承是相反的。

    在您的示例中,根据编码规则,Shape必须是抽象类。因此shape只能声明纯虚拟函数,如Print()、Load()、rotate(),。。。

    要从另一个实现继承(在形状层次结构旁边),不应使用公共继承。