Herencia en C++
Saludos, como comenté en el post anterior de Clases en C++ el modificador de acceso protegido o protected lo revisaremos ahora, pero antes de entender sobre el mismo vamos a revisar de manera rápida lo que es la herencia en POO.
Herencia
Vamos a imaginar que tenemos una clase llamada Perro en nuestro programa, un perro tiene nombre, edad y un dueño.
class Dog {
private:
int age;
char *name, *ownersName;
public:
// Contructor
Dog(int age, char *name, char *ownersName) {
this->age = age;
this->name = name;
this->ownersName;
}
};
Ahora vamos a imaginar que tenemos una clase llamada Caballo en nuestro programa, dicho caballo tiene edad y peso;
class Horse {
private:
int age;
float weight;
public:
// Constructor
Horse(int age, float weight) {
this->age=age;
this->weight = weight;
}
};
Hasta aquí todo está bien, son dos clases diferentes que pertenecen a dos animales diferentes, espera espera, dije "dos animales". Ya que ambos son animales deben tener cosas en común, podríamos tener solo una clase Animal, pero el problema es que no todos los animales tienen las mismas características (Ejem. Un humano no tiene plumas). Es aquí donde la herencia viene a ayudarnos.
De la misma manera que en los seres vivos la herencia nos hace tener ciertas características traídas de nuestros antecesores (ojos marrones o azules, cabello rizado o liso, etc.) En OOP la herencia nos permite crear clases que tienen características en común con una clase padre, para ello lo haremos de la siquiente manera.
class Animal {
/**
* El modificador de acceso protegido permite que todas las clases "hijas",
* es decir todas las clases que hereden de esta clase puedan acceder a sus
* variables o funciones pero estas no puede ser accedidas desde el exterior
*/
protected:
int age;
public:
/**
* Otra forma de crear un costructor es usar
* :variableClase(parametroConstructor)
* :age(age) -> el primer age es la variable
* de la clase y el segundo es el parametro del constructor
*/
Animal(int age): age(age) {
cout << "Constructor called for Animal object" << endl;
}
~Animal() {
cout << "Destructor called for Animal Object" << endl;
}
};
Perfecto tenemos una clase animal con una variable de edad que será la que compartan las clases hijas.
Para heredar la clase Animal hacia otra clase lo haremos de la siguiente manera:
class Gato: public Animal{...}
Veamos el siguiente ejemplo.
// Clase Dog
class Dog: public Animal {
private:
char *name, *ownersName;
public:
/**
* Para pasar la edad hacia la clase Animal
* a traves del constructor de nuestra clase Dog
* usamos tenemos que recibir la edad como parametro
* en el constructor y mandarlo hacia animal utilizando
* :Animal(parametroEdad)
*/
Dog(int age, char *name, char *ownersName): Animal(age) {
this->name = name;
this->ownersName = ownersName;
cout << "Constructor called for Dog object" << endl;
}
~Dog() {
cout << "Destructor called for Dog object" << endl;
}
// Funciones públicas
void printDogInfo() {
cout << "Name is: " << this->name << " has " << this->age
<< " years old and its owner is: " << this->ownersName << endl;
}
};
// Clase Horse
class Horse: public Animal {
private:
float weight;
public:
// Constructor & Destructor
Horse(int age, float weight): Animal(age) {
this->weight = weight;
cout << "Constructor called for Horse object" << endl;
}
~Horse() {
cout << "Destructor called for Horse object" << endl;
}
// Funciones públicas
void printHorseInfo() {
cout << "The horse has: " << this->age << " years old and weights: "
<< this->weight << " kilograms" << endl;
}
};
Ahora para poder utilizar estas clases en nuestro main lo haremos como con cualquier clase.
int main() {
// Variables para clase Dog
char dogName[10] = "Max";
char ownersName[10] = "Jon";
int dogAge = 1;
// Nueva instancia de la clase Dog y llamada a su función de impresión
Dog *dog = new Dog(dogAge, dogName, ownersName);
dog->printDogInfo();
' delete dog; // Liberamos a la memoria de la clase Dog
// Variables para clase Horse
int horseAge = 4;
float horseWeight = 312.953;
// Nueva instancia de la clase Horse y llamada a su función de impresión
Horse *horse = new Horse(horseAge, horseWeight);
horse->printHorseInfo();
' delete horse; // Liberamos a la memoria de la clase Horse
return 0;
Después de compilar nuestro programa y correrlo la respuesta que obtendremos será la siguiente:
Constructor called for Animal object
Constructor called for Dog object
Name is: Max has 1 years old and its owner is: Jon
Destructor called for Dog object
Destructor called for Animal Object
Constructor called for Animal object
Constructor called for Horse object
The horse has: 4 years old and weights: 312.953 kilograms
Destructor called for Horse object
Destructor called for Animal Object
Como podemos ver al momento de iniciar la clase "Dog" se llama a su clase padre y primero se inicia la clase "Animal", de manera invertida cuando vamos a liberar la memoria, primero llamamos al destructor de la clase "Dog" y luego al de la clase "Animal"
El código de este ejemplo lo pueden ver en:
https://github.com/nano-bytes/cpp-compilation/blob/master/classes/main-inheritance.cpp
Hasta otra
Happy Hacking!