接口类与C ++中的实现类之间的并行继承 [英] Parallel Inheritance between Interface Classes and Implementation Classes in C++

查看:117
本文介绍了接口类与C ++中的实现类之间的并行继承的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想用类似于Java接口的方式使用C ++抽象基类。假设我们有以下只有纯虚函数的接口类:

I'm trying to use C++ abstract base class in the way similar with Java interface. Supposed that we have following interface classes with only pure virtual functions:

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; };

,我尝试通过以下方式实现Square和Rectangle:

and I try to implement Square and Rectangle the following way:

class SquareImpl : public Square { /*implementation*/ };
class RectangleImpl : public SquareImpl, Rectangle { /*implementation*/ };

其中 RectangleImpl 继承 SquareImpl Rectangle 以重用,例如 SquareImpl :: area()。但是,当我尝试编译时,会出现两个问题:首先, SquareImpl 中的所有方法都不能正确继承,我必须手动重新实现 RectangleImpl :: area() RectangleImpl :: setLength()。其次,这仍然引入了 Shape RectangleImpl 的不确定基础的钻石问题。

Where RectangleImpl inherits both SquareImpl and Rectangle to reuse, say, SquareImpl::area(). However when I try to compile, two problems arise: Firstly, all methods in SquareImpl do not get inherited properly and I have to manually reimplement RectangleImpl::area() and RectangleImpl::setLength(). Secondly, this still introduces the diamond problem that Shape is ambiguous base of RectangleImpl.

如果我几乎从 Shape 继承 Square ,我可以编译代码,认为性能将随着更多派生接口添加而扩展。另外奇怪的是, RectangleImpl 仍然不继承 SquareImpl :: setLength() :area()被继承得很好。 (忽略这里的实用性)

I could compile the code if I virtually inherit Square from Shape, but I don't think the performance will scale with more derived interfaces added. Also strangely, RectangleImpl still doesn't inherit SquareImpl::setLength() although SquareImpl::area() is inherited well. (ignore the practicality here)

另一个解决方案可能是使接口彼此独立,即使 Square 不是继承自 Shape 。但是这样做会使我无法访问 Shape 中的方法,如果我定义了一个带有 Square * 指针的函数。它还将使 Shape Square 之间的static_cast不可能。

Another solution might be to make interfaces independent of each other, i.e. to make Square not inherited from Shape. But doing so will make me lose access to methods in Shape if I define functions that take a Square* pointer. It will also make static_cast impossible between Shape and Square.

所以我的问题是,有没有任何其他设计模式在C + +解决这种类型的接口类和实现类之间的并行继承,而不需要虚拟继承?

So my question is, is there any other design pattern in C++ to solve this kind of parallel inheritance between interface classes and implementation classes, without requiring virtual inheritance?

编辑澄清:上面的示例代码只是我的接口和实现之间的并行继承的虚假插图。我理解有更好的方法来实现形状,但我的问题不是如何实现形状。)

(edit clarification: the example code above are just my dummy illustration on parallel inheritance between interfaces and implementations. I understand that there are better ways to implement shapes but my problem is not on how to implement shapes.)

推荐答案

这里的是 Diamond Problem ,它可以在允许多重继承的任何OO语言中发生。顺便说一句,这是为什么Java的设计者决定不具有多重继承,并提出了接口的概念的一个原因。

What you have here is the case of the Diamond Problem, which can happen in any OO language that allows multiple inheritance. This, by the way, is one reason why the designers of Java decided not to have multiple inheritance, and came up with the notion of an interface.

C ++的方式与钻石问题是虚拟继承

The way C++ deals with the diamond problem is Virtual Inheritance.

并且,正如codymanix指出的,正方形和矩形是面向对象设计的一个臭名昭着的糟糕的例子,因为就OO而言一个正方形不是一个矩形

And, as codymanix pointed out, the square and the rectangle is a notoriously bad example for object oriented design, because as far as OO is concerned a square is not a rectangle.

几个点。首先,你在这里所做的事情是多重继承,而不是并行继承。第二,在这种特殊情况下,有一个类Square 类SquareImpl 真的没有意义。如果你认为你可能有不同的实现 Square ,你应该只有一个基类提供一个默认实现和虚拟函数,如果必要的话可以被派生类重写。换句话说,你应该将 Square SquareImpl 转换成一个具有虚拟函数的类。

Couple more points. First, The term for what you are doing here is multiple inheritance, not "parallel inheritance". Second, in this particular case it really makes little sense to have a class Square and a class SquareImpl. If you think you may have different implementations of Square, you should just have one base class which provides a default implementation and virtual functions that can be overridden by a derived class if necessary. In other words, you should roll Square and SquareImpl into one class with virtual functions.

你当然可以使用像Java接口一样的抽象C ++类,但大多数时候没有理由。接口被添加到Java精确作为一种方法来摆脱缺乏多重继承。在C ++中,你可以继续使用多重继承,虽然你应该总是这样做非常审慎。

You certainly can use an abstract C++ class like a Java interface, but most of the time there is no reason for it. Interfaces were added to Java precisely as a way to get around the lack of multiple inheritance. In C++ you can just go ahead and use multiple inheritance, although you should always do that very judiciously.

这篇关于接口类与C ++中的实现类之间的并行继承的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆