Herencia simple
La herencia simple es la más típica, la que se puede encontrar en cualquier lenguaje moderno como Java o C#.
La
herencia simple es una relación entre una clase padre (clase base) y
una clase hija (clase derivada) llamada "es un tipo de", que muchas
veces se abrevia como isA.
La herencia es simple cuando la clase derivada que estamos considerando sólo tiene una clase base.
Un ejemplo sería el siguiente:
#include <iostream>
using namespace std;
class Vehiculo {
public:
void avanza() {}
};
class Coche : public Vehiculo {
public:
void avanza(void)
{ cout << "Avanza coche." << endl; }
};
class Moto: public Vehiculo {
public:
void avanza(void)
{ cout << "Avanza moto." << endl; }
};
int main()
{
Moto t;
Coche c;
t.avanza();
c.avanza();
return 0;
}
Esta
es la herencia más útil y típica. Existen otros
tipos de herencia marginales en C++, que se describen a
continuación, pero que en la práctica son poco
útiles.
Más tipos de herencia
Los
métodos que coinciden en nombre y en tipos y número de argumentos son
sobreescritos, de manera que cuando se llama al método avanza() del
objeto c se llama al que realmente corresponde.
Pero, en realidad, existen dos tipos de herencia más: la herencia privada (private), y la herencia protegida (protegida).
Ambas modifican la visibilidad de los miembros de la clase base
(Vehículo, en el ejemplo), en la clase derivada (Coche o Moto,
de nuevo en el ejemplo). Así:
#include <iostream>
using namespace std;
class Vehiculo {
public:
void avanza() { cout << "Avanza vehículo" << endl; }
};
class Coche : private Vehiculo {
};
class Moto: protected Vehiculo {
};
int main()
{
Moto t;
Coche c;
t.avanza();
c.avanza();
return 0;
}
Ahora las líneas t.avanza() y c.avanza()
ya no compilan en la función main(), puesto que lo que era
público en Vehículo ha pasado a ser privado en Coche,
mientras que los mismos miembros de vehículo han pasado a ser
protegidos en Moto. De esta manera, es posible crear clases que oculten
sus partes Vehículo, y permitan escoger cuáles miembros
van a ser visibles y cuáles no.
#include <iostream>
using namespace std;
class Vehiculo {
public:
void avanza() { cout << "Avanza vehículo" << endl; }
};
class Coche : private Vehiculo {
public:
using Vehiculo::avanza;
};
int main()
{
Coche c;
c.avanza();
return 0;
}
Ahora,
el programa vuelve a funcionar. Sin embargo, la herencia privada o
protegida hacen que realmente la clase se desvincule totalmente de la
jerarquía de herehcia. Así, debería ser posible
utilizar un Coche en cualquier lugar del programa donde se utilice un
Vehículo, sin embargo el compilador no lo permitirá. La
razón es que la parte Vehículo dentro de Coche (o de
Moto), está escondida y no es accesible (al fin y al cabo, se ha
marcado como private o protected).
Estos dos tipos de herencia son, por tanto, muy poco útiles, y en general, también poco recomendables.