como Herb Sutter y Andrei Alexandrescu explican en su libro C++ Coding Standards (item 34), la herencia es una de las relaciones más estrechas, que C++ permite utilizar entre dos clases - Es el segundo a una relación friend
entre clases.
De acuerdo con S.O.L.I.D principles of OO, un diseño exitoso debe apuntar a acoplamiento flojo entre clases - esto implica mantener las dependencias al mínimo; lo que a su vez implica que la herencia es una herramienta que debe usarse con cuidado.
Por supuesto, las dependencias en general, tienen que existir en algún lugar , por lo que un compromiso razonable se puede heredar de clases sin aplicación en absoluto (análoga a los llamados interface
s en lenguajes como C# y Java). p.ej.
class IDriveable
{
public:
virtual void GoForward() = 0;
virtual void GoBackward() = 0;
};
class Car : public IDriveable { /* etc. */ };
class Bus : public IDriveable { /* etc. */ };
class Train : public IDriveable { /* etc. */ };
Con este enfoque, si tiene elementos de código que se reutilizan entre varias clases Disfruta de la conducción, lo más habitual es utilizar composición o alguna otra relación más débil para eliminar código repetido.
p. quizás desea volver a utilizar el código de TurnLeft
para un Bus
y una Car
pero no un Train
donde girando a la izquierda es ilógico, por lo TurnLeft
podría terminar en una clase separada que es un miembro de Bus
y Car
.
- Además, cualquier funcionalidad que pueda necesita saber acerca de todas las clases relacionadas vagamente sería externa a la jerarquía de clases, sólo es consciente de la interfaz/base en lugar de los detalles de implementación meollo de la cuestión.
El resultado final puede ser una pequeña cantidad de código adicional para la composición, pero a menudo un diseño menos complejo, y normalmente uno que es más fácil de administrar. No existen reglas estrictas para diseñar código como este, ya que depende completamente de los problemas únicos que intenta resolver.
Hay otras formas de reutilizar código sin estrecho acoplamiento también - plantillas permiten definir implícitamente las interfaces sin clases vacías que contienen puros virtual
funciones (plantillas proporcionan la seguridad de tipos adicionales - que es una muy buena cosa, pero son sintácticamente una poco más complejo);
Y hay formas en las que puede usar std::function
y lambdas para volver a utilizar el código en un estilo más funcional: una vez más, normalmente no hay dependencias estrictas al pasar alrededor de los objetos de función.
Gracias por las respuestas chicos! Realmente los aprecio La razón por la que consideré usar herencia en lugar de composición es porque también necesito modificar algunos comportamientos en A y B. Además, realmente no quiero editar A y B. – user1657624