2009-07-07 22 views
10

Para ser claro, no estoy preguntando si/por qué la herencia múltiple es buena o mala. He escuchado muchos argumentos de ambos lados de ese debate.¿Cuándo podría la herencia múltiple ser la única solución razonable?

Me pregunto si hay algún tipo de problema de diseño o escenario en C++ en el que la herencia múltiple sea la única forma de lograr algo, o al menos sea la forma más óptima sobre todas las demás alternativas al punto que no tendría sentido considerar nada más.

Obviamente, esta pregunta no se aplica a los idiomas que no admiten la herencia múltiple.

+0

Una pregunta similar: http://stackoverflow.com/questions/573913/a-use-for-multiple-inheritance –

Respuesta

10

No puede hacer policy-based design sin herencia múltiple. Entonces, si el diseño basado en políticas es la manera más elegante de resolver su problema, entonces eso significa que necesita una herencia múltiple para resolver su problema, sobre todas las demás opciones.

La herencia múltiple puede ser muy útil si no se usa incorrectamente (como todo, en cualquier idioma).

+2

¿Esto implica que el diseño basado en políticas simplemente no es posible en un idioma como Java, o hay formas de evitarlo? –

+0

En realidad, el artículo enlazado indica que la herencia múltiple es sólo el patrón de aplicación más común (con algunas ventajas significativas), no es que sea absolutamente necesario. – GalacticCowboy

+0

@Jeff L: la clase 'Proxy' en Java se puede usar como una solución alternativa. – finnw

5

Hay una situación en la que heredarías de una clase y tal vez implementarías una o dos interfaces en Java. Esto es algo que resolverías con herencia múltiple en C++, creo.

2

He leído sobre Java Interfaces, y así sucesivamente, para tener una mejor idea de la respuesta a esta pregunta. La idea detrás de una interfaz es crear una clase abstracta que actúe como plantilla para otra clase. la ventaja, aquí, es que las plantillas se pueden combinar dentro de una clase concreta. Por ejemplo-

Padres Foodstore de clase Subclass- CoffeeShop Subclass- panadería

Con este árbol de herencia, un Foodstore puede ser una panadería o una cafetería, pero no ambos. Pero entonces, ¿qué llamaríamos un Starbucks?

mejor manera, IMO

Padres Class- Foodstore Interface- CoffeeShop Interface- panadería

clase pública se extiende Starbucks Foodstore implementa CoffeeShop, Panadería {...}

podrás tiene que saber un poco de Java para entender eso, pero tiene que hacerlo. Las interfaces son bastante elementales, IMO.

Como una reflexión adicional, tal vez las interfaces están diseñadas para obedecer "No te repitas". Obvio, ahora que lo menciono.

3

La herencia múltiple es útil si se necesita para heredar el comportamiento , no sólo contrato. Sin embargo, como demuestran otros lenguajes, la herencia múltiple no es la única forma de resolver ese problema, a expensas de hacer que su árbol de herencia sea más profundo. Como tal, los escenarios en los que deben y pueden solo usar herencia múltiple sería bastante raro.

0

Como se ha dicho en las otras respuestas:

  • usando clases base virtual pura como "Interfaces", como en Java (http://en.wikipedia.org/wiki/Interface_(Java)), este es un muy común O.Ö. patrón en todos los O.O.idiomas, no sólo Java

  • Para hacer basado en el diseño de policía

Pero también:

  • Para componer una clase con varios mixins (http://en.wikipedia.org/wiki/Mixin); Considero que es un buen uso de la herencia múltiple para lograr la reutilización del código.
3

C++ utilizan corrientes herencia múltiple: istream y ostream son ambos padres de iostream. Como ambos heredan de ios_base, tienes un diamante.

Es la única solución "razonable" en el sentido de que no sería razonable que las secuencias de las bibliotecas estándar tomaran la misma línea que los algoritmos y las colecciones. Así que ostream se comporta polimórficamente en lugar de ser una interfaz tipo "pato" como Iterator (*).

Tan pronto como tengas un polimorfismo dinámico, necesitas herencia múltiple para implementar más de una interfaz al mismo tiempo.

(*) Presumiblemente, esto se debe a que cualquier otra cosa sería un caos. Debe poder escribir funciones reales que manipulen flujos, en lugar de forzar a los usuarios a tener plantillas en todas partes. Esto se debe a que es común escribir en "algún flujo, no sé qué hasta el tiempo de ejecución", pero no querer manipular "alguna colección, no sé qué hasta el tiempo de ejecución".

1

Cuando desea heredar funcionalidad en lugar de papel, ejemplo de ello boost::noncopyable (otros lenguajes que soportan este (a diferencia de Java y C#) llaman a esto un mixin ).

0

Cuando debe combinar dos o más jerarquías de clases de terceros, cada una de las cuales requiere que los objetos se deriven de la propia clase Base de la jerarquía, entonces la falta de herencia múltiple hará que su código sea complejo e incómodo.

namespace Object_Database { 
    class Object { 
     public: 
     virtual void store() ; 
     virtual void fetch() ; 
    }; 
} 

namespace Reflectives { 
    class Object { 
     public: 
     virtual std::vector<std::string> > membernames(); 
     virtual std::vector<std::string> > methodnames(); 
    }; 
} 

La primera jerarquía permite a los usuarios crear objetos que se pueden serializar hacia y desde una base de datos de objeto, y requiere que todos los tales objetos pueden derivar de Object_Database clase :: Object. La segunda jerarquía permite a los usuarios crear objetos que se pueden consultar en el tiempo de ejecución para los nombres de sus miembros, y requiere que todos esos objetos se deriven de Reflectives :: Object.

Si requiere objetos que se pueden hacer las dos cosas, sólo tiene que escribir:

class ReflectivePickle : 
    public Object_Database::Object, 
    public Reflectives::Object { 
    // ... 
    }; 

Las otras soluciones no son razonables.

0

Tiendo a usar herencia múltiple en C++ cuando las clases base son "clases de interfaz", es decir, clases base donde todos los métodos son puros virtuales, ninguno tiene implementaciones [recuerde que todavía puede definir una implementación, pero debe invocarla explícitamente], y no hay miembros de datos. Muy similar a "interfaces" en Java o (por lo que escucho) C#.

Para usar el polimorfismo en C++, no puede usar la composición, tiene que usar la herencia (pública).

De modo que si la barra de clases hereda (públicamente) de Printable y Serializable, puedo tratar el objeto como un objeto imprimible, un objeto serializable o un objeto Bar (usando punteros o referencias).

con la composición, no se puede hacer eso.

0

Si desea ver una hermosa puesta en práctica de herencia múltiple echa un vistazo a Eiffel. Resuelven el problema de diamantes a través de cambio de nombre de función, mucho más simple que resolución de alcance e incluso admite la herencia repetida directa de tal manera que:

Un hereda B, B, B

cuando surge la necesidad de utilizar este tipo de herencia.

Su biblioteca del núcleo es de código abierto y la herencia múltiple se utiliza ampliamente si le gustaría ver ejemplos.

http://sourceforge.net/projects/eiffelstudio/files/