Soa*_*res 6 c++ design-patterns interface multiple-inheritance
我试图以类似于Java接口的方式使用C++抽象基类.假设我们有以下只有纯虚函数的接口类:
class Shape { virtual double area()=0; };
class Square : public Shape { virtual void setLength(double length)=0; };
class Rectangle : public Square { virtual void setWidth(double width)=0; };
Run Code Online (Sandbox Code Playgroud)
我尝试通过以下方式实现Square和Rectangle:
class SquareImpl : public Square { /*implementation*/ };
class RectangleImpl : public SquareImpl, Rectangle { /*implementation*/ };
Run Code Online (Sandbox Code Playgroud)
凡RectangleImpl同时继承了SquareImpl与Rectangle重用,说,SquareImpl::area().但是当我尝试编译时,出现了两个问题:首先,所有方法SquareImpl都没有得到正确的继承,我必须手动重新实现RectangleImpl::area()和RectangleImpl::setLength().其次,这仍然引入了Shape模糊基础的钻石问题RectangleImpl.
如果我真的继承Square了Shape,我可以编译代码,但我不认为性能会随着添加的更多派生接口而扩展.同样奇怪的是,虽然继承得很好,RectangleImpl但仍然没有继承.(忽略这里的实用性)SquareImpl::setLength()SquareImpl::area()
另一种解决方案可能是使接口彼此独立,即不使其Square继承Shape.但是Shape如果我定义了带有Square*指针的函数,那么这样做会让我失去对方法的访问权限.它也会使Shape和之间的static_cast无法实现Square.
所以我的问题是,C++中是否还有其他设计模式来解决接口类和实现类之间的这种并行继承,而不需要虚拟继承?
(编辑说明:上面的示例代码只是我对接口和实现之间并行继承的虚拟说明.我知道有更好的方法来实现形状,但我的问题不在于如何实现形状.)
这里的情况是钻石问题,它可能发生在任何允许多重继承的面向对象语言中。顺便说一下,这就是 Java 设计者决定不使用多重继承并提出接口概念的原因之一。
C++处理钻石问题的方式是虚拟继承。
而且,正如 codymanix 指出的那样,正方形和矩形对于面向对象设计来说是一个臭名昭著的糟糕例子,因为就 OO 而言,正方形不是矩形。
再加上几点。首先,您在这里所做的术语是多重继承,而不是“并行继承”。其次,在这种特殊情况下,使用 aclass Square和 a确实没有什么意义class SquareImpl。如果您认为您可能有不同的 实现Square,那么您应该只拥有一个基类,该基类提供默认实现和虚拟函数,必要时可以由派生类覆盖这些函数。换句话说,您应该将Square和SquareImpl归入一个具有虚函数的类。
您当然可以像 Java 接口一样使用抽象 C++ 类,但大多数时候没有理由这样做。Java 中添加接口正是为了解决缺乏多重继承的问题。在 C++ 中,您可以继续使用多重继承,尽管您应该始终非常明智地这样做。
| 归档时间: |
|
| 查看次数: |
2158 次 |
| 最近记录: |