En C++ la herencia se utiliza para establecer una relación entre una clase base (o clase padre) y una clase derivada (o clase hija).
La clase derivada cuenta con todas las características públicas y protegidas de la clase base, además de las suyas propias. Esto le que permite extender o modificar el comportamiento de la clase base.
Implementación de la Herencia en C++
La herencia en C++ se define utilizando la sintaxis de dos puntos (:
) seguida del tipo de herencia (public
, protected
, o private
) y el nombre de la clase base.
class ClaseBase
{
// Miembros de la clase base
};
class ClaseDerivada : public ClaseBase
{
// Miembros adicionales de la clase derivada
};
Vamos a crear un ejemplo simple donde una clase Animal
es la clase base y una clase Perro
es la clase derivada:
#include <iostream>
class Animal
{
public:
void Comer()
{
std::cout << "El animal está comiendo." << std::endl;
}
};
class Perro : public Animal
{
public:
void Ladrar()
{
std::cout << "El perro está ladrando." << std::endl;
}
};
int main()
{
Perro miPerro;
miPerro.Comer(); // Heredado de Animal
miPerro.Ladrar(); // Método definido en Perro
return 0;
}
En este ejemplo,
- La clase
Perro
hereda deAnimal
- Esto lo que significa que
Perro
tiene acceso al métodoComer
deAnimal
- Además de su propio método
Ladrar
.
Acceso a miembros clase padre
Puedes acceder a los miembros de la clase base directamente usando el nombre de la clase base seguido del operador de resolución de ámbito (::
).
#include <iostream>
class Animal
{
public:
std::string Nombre;
Animal(const std::string& nombre) : Nombre(nombre) {}
virtual void HacerSonido()
{
std::cout << "El animal hace un sonido." << std::endl;
}
};
class Perro : public Animal
{
public:
Perro(const std::string& nombre) : Animal(nombre) {}
void HacerSonido() override
{
Animal::HacerSonido(); // Llama al método de la clase base
std::cout << "El perro ladra." << std::endl;
}
};
int main()
{
Perro miPerro("Rex");
miPerro.HacerSonido(); // Salida: El animal hace un sonido. El perro ladra.
return 0;
}
Sobrescritura de Métodos
Las clases derivadas pueden sobrescribir métodos de la clase base para proporcionar una implementación específica.
Para hacerlo, el método en la clase base debe ser declarado con la palabra clave virtual
, y el método en la clase derivada debe usar la palabra clave override
.
#include <iostream>
class Animal
{
public:
virtual void HacerSonido()
{
std::cout << "El animal hace un sonido." << std::endl;
}
};
class Perro : public Animal
{
public:
void HacerSonido() override
{
std::cout << "El perro ladra." << std::endl;
}
};
int main()
{
Animal* miAnimal = new Perro();
miAnimal->HacerSonido(); // Llama al método sobrescrito en Perro
delete miAnimal;
return 0;
}
En este ejemplo,
Perro
sobrescribe el métodoHacerSonido
deAnimal
.- Cuando llamamos a
HacerSonido
a través de un puntero aAnimal
, se ejecuta la versión sobrescrita enPerro
.
Constructores en clases derivadas
Cuando se crea una instancia de una clase derivada, el constructor de la clase base se llama automáticamente antes del constructor de la clase derivada.
Puedes especificar qué constructor de la clase base se debe llamar utilizando el inicializador de lista de la clase derivada.
#include <iostream>
class Animal
{
public:
std::string Nombre;
Animal(const std::string& nombre) : Nombre(nombre) {}
void MostrarNombre()
{
std::cout << "Nombre: " << Nombre << std::endl;
}
};
class Perro : public Animal
{
public:
std::string Raza;
Perro(const std::string& nombre, const std::string& raza)
: Animal(nombre), Raza(raza) {}
void MostrarInfo()
{
MostrarNombre();
std::cout << "Raza: " << Raza << std::endl;
}
};
int main()
{
Perro miPerro("Rex", "Labrador");
miPerro.MostrarInfo(); // Salida: Nombre: Rex Raza: Labrador
return 0;
}
En este ejemplo, el constructor de Perro
llama al constructor de Animal
para inicializar el campo Nombre
.