Herencia

Es una característica del lenguaje que permite definir a una clase (Derivada) en términos de otra (Base). En este caso Derivada hereda de Base, lo que significa que Derivada está definida en términos de Base. Hay mucho más sobre el tema, pero por ahora es conveniente dejarlo en una herencia pública y sencilla (no múltiple).

Construcción y destrucción

Teniendo varios niveles de herencia, y asumiendo la siguiente jerarquía: A es la clase base, B hereda de A, C hereda de B. El orden de construcción de un objeto es A-B-C. El orden de destrucción es el inverso: C-B-A. El primer sub-objeto en construirse es de la clase base que está más arriba A, a partir de este se construye el de la siguiente en jerarquía B, y finalmente el de la última clase derivada C.

Código

Para ilustrarlo en código C++, se puede apreciar la construcción y destrucción de los sub-objetos de una herencia pública simple en la cola (stack).

Destructor virtual

De manera similar, se puede crear un objeto polimórfico alojado en la pila (heap); sin embargo, para que la memoria sea liberada correctamente es requerido que los destructores sean virtuales, de lo contrario se produce una fuga de memoria pues solamente es invocado el destructor de la clase base.

En el ejemplo anterior se pueden realizar los ajustes:

struct Abue{
  virtual ~Abue() {/*...*/};
};
struct Mama : public Abue{
  ~Mama() override {/*...*/};
};
struct Yo : public Mama{
  ~Yo() override {/*...*/};
};

Ahora se puede crear un puntero que libera la memoria correctamente:

Abue* unYo = new Yo();
delete unYo;

std::unique_ptr<Abue> otroYo = std::make_unique<Yo>();

La recomendación es siempre usar destructores virtuales cuando se usa herencia, teniendo en cuenta la Regla de 5.
Para std::shared_ptr el manejo es diferente.
Para profundizar sobre el tema ver 1 y 2.

Fuentes


Deja un comentario