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
-
The Cherno Virtual destructors in C++ ↩
Deja un comentario