utiliza tipos que porque por multiples multiple herencias herencia hay existen c++ multiple-inheritance

c++ - tipos - porque java no utiliza herencia multiple



¿Cómo puedo evitar el Diamante de la Muerte cuando uso herencia múltiple? (9)

http://en.wikipedia.org/wiki/Diamond_problem

Sé lo que significa, pero ¿qué pasos puedo tomar para evitarlo?


Bueno, lo mejor de Dreaded Diamond es que es un error cuando ocurre. La mejor manera de evitarlo es averiguar de antemano su estructura de herencia. Por ejemplo, un proyecto en el que trabajo tiene visores y editores. Los editores son subclases lógicas de los espectadores, pero como todos los espectadores son subclases: TextViewer, ImageViewer, etc., el editor no deriva del visor, lo que permite que las clases finales del editor de textos, ImageEditor eviten el diamante.

En casos donde el diamante no es evitable, usando herencia virtual. La mayor advertencia, sin embargo, con bases virtuales, es que el constructor para la base virtual debe ser llamado por la clase más derivada, lo que significa que una clase que se deriva virtualmente no tiene control sobre los parámetros del constructor. Además, la presencia de una base virtual tiende a incurrir en una penalización de rendimiento / espacio en el casting a través de la cadena, aunque no creo que haya mucho de penalización por más allá del primero.

Además, siempre puedes usar el diamante si eres explícito sobre qué base quieres usar. A veces es la única forma.



La herencia es un arma fuerte y fuerte. Úselo solo cuando realmente lo necesite. En el pasado, la herencia de diamantes era una señal de que iba muy lejos con la clasificación, diciendo que un usuario es un "empleado" pero también es un "oyente de widgets", pero también un ...

En estos casos, es fácil acceder a múltiples problemas de herencia.

Los resolví mediante el uso de la composición y los indicadores para el propietario:

Antes de:

class Employee : public WidgetListener, public LectureAttendee { public: Employee(int x, int y) WidgetListener(x), LectureAttendee(y) {} };

Después:

class Employee { public: Employee(int x, int y) : listener(this, x), attendee(this, y) {} WidgetListener listener; LectureAttendee attendee; };

Sí, los derechos de acceso son diferentes, pero si puedes salirte con la suya sin duplicar el código, es mejor porque es menos poderoso. (Puede ahorrar energía cuando no tenga alternativa).


Me limitaría a usar herencia múltiple de interfaces solamente. Si bien la herencia de clases múltiples es atractiva a veces, también puede ser confusa y dolorosa si se basa en ella regularmente.


Sugeriría un mejor diseño de clase. Estoy seguro de que hay algunos problemas que se resuelven mejor a través de la herencia múltiple, pero verifique si hay otro camino primero.

Si no, use funciones / interfaces virtuales.


Un ejemplo práctico:

class A {}; class B : public A {}; class C : public A {}; class D : public B, public C {};

Observe cómo la clase D hereda de B y C. Pero ambos B y C heredan de A. Eso dará como resultado que se incluyan 2 copias de la clase A en el vtable.

Para resolver esto, necesitamos herencia virtual. Es la clase A que necesita ser virtualmente heredada. Por lo tanto, esto solucionará el problema:

class A {}; class B : virtual public A {}; class C : virtual public A {}; class D : public B, public C {};


Usa herencia por delegación. Entonces ambas clases apuntarán a una base A, pero tendrán que implementar métodos que redirijan a A. Tiene el efecto secundario de convertir miembros protegidos de A en miembros "privados" en B, C y D, pero ahora no necesita virtual, y no tienes un diamante.


herencia virtual. Para eso está ahí.


class A {}; class B : public A {}; class C : public A {}; class D : public B, public C {};

En esto, los atributos de la Clase A se repiten dos veces en la Clase D, lo que hace que se use más memoria ... Por lo tanto, para ahorrar memoria, hacemos un atributo virtual para todos los atributos heredados de la clase A que están almacenados en un Vtable.