Sunteți pe pagina 1din 6

Herencia I

Una razón para utilizar la herencia es que permite reutilizar código de proyectos
anteriores dándole la flexibilidad de hacer ligeras modificaciones si el viejo código no
hace exactamente lo que Usted necesita en su nuevo proyecto. No tiene sentido
empezar cada nuevo proyecto desde cero ya que una parte del código ciertamente
será reutilizado en varios programas, sin embargo, es fácil cometer un error si Usted
trata de modificar la clase original. Otra razón para utilizar la herencia es si el proyecto
requiere de varias clases las cuales son muy similares pero con algunas diferencias. En
éste capítulo nos concentraremos en el mecanismo de la herencia y cómo
implementarla en un programa. C++ permite heredar toda o una parte de los
miembros ó métodos de una clase, modificar algunos y agregar nuevos miembros si
no están disponibles en la clase padre.

Una clase simple


El archivo de cabecera llamado vehiculo.h contiene una clase sencilla que
utilizaremos para empezar nuestro estudio de la herencia, consiste de cuatro métodos
los cuales pueden utilizarse para manipular los datos relativos a nuestro vehiculo, lo
que hace cada método no es especialmente importante en éste momento,
eventualmente nos referiremos a ésta clase como la clase base ó padre, pero mientras
tanto la utilizaremos como cualquier otra clase para demostrar que no hay nada que la
diferencíe de otras clases, la palabra clave protected la estudiaremos más adelante
en ésta misma lección.
// Archivo de cabecera vehiculo.h float peso;
public:
#ifndef VEHICULO_H void inicializa(int in_llantas, float in_peso);
#define VEHICULO_H int obtiene_llantas(void);
float obtiene_peso(void);
class vehiculo float llanta_carga(void);
{ };
protected:
int llantas; #endif

La implementación de vehiculo

En el siguiente código, llamado vehiculo.cpp encontrará la implementación de la


clase vehiculo. El método inicializa ( ) los valores de entrada como parámetros a las
variables llantas y peso. Disponemos de métodos para retornar el número de llantas
y el peso y por último, tenemos un método que hace un cálculo trivial que retorna la
carga en cada llanta. Más adelante veremos métodos que hagan procesos más
significativos, pero en éste momento lo importante es comprender como implementar
la herencia de clases.

// Archivo vehiculo.cpp llantas = in_llantas;


peso = in_peso;
#include "vehiculo.h" }

// inicializa a cualquier dato deseado // obtiene el numero de llantas del vehiculo


void vehiculo::inicializa(int in_llantas, float int vehiculo::obtiene_llantas()
in_peso) {
{ return llantas;
}
// retorna el peso en cada llanta
// retorna el peso del vehiculo float vehiculo::llanta_carga()
float vehiculo::obtiene_peso() {
{ return peso/llantas;
return peso; }
}

Utilizando la clase vehículo

Se recomienda crear una carpeta para guardar en ella los archivos vehiculo.h y
vehiculo.cpp ya que serán utilizados en los siguientes ejemplos, empezando con el
siguiente programa cuyo código llamado transpte.cpp utiliza la clase vehiculo que
nosotros haremos un poco especial utilizandola sin modificación como clase base en
los próximos ejemplos para ilustrar la herencia, ésta utiliza una clase existente y le
agrega funcionalidad para cumplir una tarea posiblemente más compleja.
// Archivo transpte.cpp
#include <iostream.h>
#include "vehiculo.h"
int main()
{
vehiculo carro, moto, camioneta, sedan;
carro.inicializa(4, 3000.0);
moto.inicializa(2, 900.0);
camioneta.inicializa(18, 45000.0);
sedan.inicializa(4, 3000.0);
cout << "El carro tiene " << carro.obtiene_llantas() << " llantas.\n";
cout << "La camioneta tiene una capacidad de " << camioneta.llanta_carga()
<< " libras por llanta.\n";
cout << "La moto pesa " << moto.obtiene_peso() << " libras.\n";
cout << "El sedan pesa " << sedan.obtiene_peso() << " libras, y tiene "
<< sedan.obtiene_llantas() << " llantas.\n";
return 0;
}
No debe haber problema alguno para comprender la operación del programa, éste
declara cuatro objetos de la clase vehiculo, los inicializa y despliega algunos datos
para ilustrar que la clase vehiculo puede ser utilizada como una clase simple porque
es en realidad una clase simple. Nos referimos a ella como una clase simple en
contraste a llamarla clase base ó clase derivada tal y como lo haremos muy pronto.
Compile y ejecute el programa, incluyendo los archivos vehiculo.cpp y vehiculo.h, el
resultado es el siguiente:

El carro tiene 4 llantas.


La camioneta tiene una capacidad de 2500 libras por llanta.
La moto pesa 900 libras
El sedan pesa 3000 libras, y tiene 4 llantas.

Una clase derivada


Como primer ejemplo del uso de una clase derivada ó clase hija tenemos el archivo
llamado carro.h. La clase vehiculo es heredada debido al enunciado class carro :
public vehiculo en la línea 8. Esta clase derivada llamada carro está compuesta de
toda la información incluida en la clase base vehiculo, y de su propia información
adicional. Para ir un paso más lejos, aunque la clase vehiculo será utilizada como
clase base en un programa de ejemplo más adelante en éste capítulo, no hay razón
para continuar utilizandola como una simple clase en el programa del ejemplo
anterior, de hecho, puede ser utilizada como clase simple y como clase base en el
mismo programa. La respuesta a cuándo es una clase simple y cuándo es una clase
base depende en cómo sea utilizada.
// Archivo de cabecera carro.h int carga_pasajeros;
public:
#ifndef CARRO_H void inicializa(int in_llantas, float in_peso, int
#define CARRO_H personas = 4);
#include "vehiculo.h" int pasajeros(void);
};
class carro : public vehiculo #endif
{

Es necesario discutir cierta terminología. Cuando hablamos de Programación


Orientada a Objetos en general, una clase que hereda otra es a menudo llamada clase
derivada ó clase hija, pero el término más adecuado de acuerdo a la definición de C+
+, es clase derivada. De la misma manera, el término adecuado en C++ para la clase
heredada es llamarla clase base aunque los términos clase padre y super clase son
también utilizados.
Una clase base es aquella que cubre un amplio rango de objetos, en tanto que una
clase derivada está algo más restringida pero al mismo tiempo más útil. Por ejemplo si
tenemos una clase base llamada lenguaje de programación y una clase derivada
llamada C++, entonces podríamos utilizar la clase base para definir Pascal, Ada, C++
o cualquier otro lenguaje de programacion, pero no puede decirnos nada acerca del
uso de las clases en C++ ya que solo puede dar una visión general de cada lenguaje.
Por otra parte, la clase derivada llamada C++ puede definir el uso de las clases pero
no se puede utilizar para describir otros lenguajes. Una clase base tiende a ser más
general y una clase derivada es más específica.
En el caso de nuestro ejemplo, la clase base vehiculo puede utilizarse para declarar
objetos que representen camiones, carros, bicicletas o cualquier otro tipo de vehiculo.
La clase llamada carro puede utilizarse solamente para declarar un objeto de tipo
carro ya que hemos limitado los tipos de datos que pueden utilizarse
inteligentemente con ésta clase. La clase carro es por lo tanto más restrictiva y
específica que la clase vehiculo. La clase vehiculo es más general que la clase
carro. Si quisieramos ser aún más específicos podríamos definir una clase derivada
utilizando carro como la clase base, por ejemplo, carro_deportivo puede ser una
clase derivada de carro, y podríamos incluir maxima_velocidad como miembro de
carro_deportivo, información que podría no aplicarse a un carro de tipo familiar.

¿Cómo se define una clase derivada?


Una clase derivada se define incluyendo el archivo de cabecera para la clase base
como lo hicimos en la línea 6, después se especifica el nombre de la clase base
seguido del nombre de la clase derivada separados por un símbolo de dos puntos,
como está ilustrado en la línea 8. Por el momento ignore la palabra clave public que
sigue del símbolo de dos puntos, ésta define una herencia de tipo public y ésto lo
estudiaremos en detalle en el próximo capítulo. Todos los objetos declarados como
parte de la clase carro están compuestos de dos variables de la clase vehiculo por
medio de la herencia y de la variable sencilla declarada en la clase carro llamada
carga_pasajeros. Un objeto de la clase carro tendrá tres de los cuatro métodos de
vehiculo y los dos nuevos declarados en carro. El método llamado inicializa ( ) el
cual es parte de la clase vehiculo no está disponible porque está oculta por la versión
local de inicializa ( ) la cual es parte de la clase carro. El método local será utilizado
si el nombre es repetido permitiendole personalizar su nueva clase. Observe que la
implementación de la clase base puede surtirse en forma compilada, el código fuente
de la implementación puede ocultarse por razones económicas en pro de los intereses
del desarrollador de la clase, esto permite a su vez la práctica de la ocultación de la
información. El archivo de cabecera para la clase base debe estar disponible como un
archivo de texto ya que las definiciones de la clase son necesarios para utilizar la
clase.

Implementación de la clase carro

El archivo llamado carro.cpp representa la implementación de la clase carro. Lo


primero que debe observar es que éste archivo no indica el hecho de que se trata de
una clase derivada de cualquier otro archivo, esto solo puede determinarse
examinando el archivo de cabecera para la clase. Como no podemos saber si es una
clase derivada o no, se escribe de la misma manera que la implementación de
cualquier otra clase.
// Archivo carro.cpp llantas = in_llantas;
#include "carro.h" peso = in_peso;
void carro::inicializa(int in_llantas, float in_peso, }
int personas) int carro::pasajeros(void){ return
{ pasajeros_carga; }
pasajeros_carga = personas;

Otra clase derivada

En el archivo camion.h tenemos otro ejemplo de una clase derivada de la clase


vehiculo, por supuesto, agrega dos variables y tres métodos de cosas relacionadas
con los camiones. Un punto importante es que la clase carro y la clase camion no
tienen relación entre sí, sucede simplemente que ambas son clases derivadas de la
misma clase base. Observe que ambas clases tienen métodos llamados pasajeros ( )
pero ésto no causa problemas y es perfectamente aceptable.
// Archivo camion.h
#ifndef CAMION_H
#define CAMION_H
#include "vehiculo.h"
class camion : public vehiculo
{
int pasajeros_carga;
float flete;
public:
void ini_camion(int cuantos = 2, float max_carga = 24000.0);
float eficiencia(void);
int pasajeros(void);
};
#endif

Implementación de camion
En el siguiente código está especificado la implementación de la clase camion, en
realidad no presenta nada nuevo, sin embargo nos será útil para demostrar como se
utilizan juntas las clases que estamos estudiando.
// Archivo camion.cpp flete = max_carga;
#include "camion.h" }
void camion::ini_camion(int cuantos, float float camion::eficiencia(void){ return flete /
max_carga) (flete + peso);}
{ int camion::pasajeros(void){ return
pasajeros_carga = cuantos; pasajeros_carga;}

Utilizando juntas las clases


El programa llamado todovehi.cpp utiliza las tres clases que hemos discutido en éste
capítulo. Utiliza la clase base vehiculo para declarar objetos y además utiliza las dos
clases derivadas para lo mismo, esto lo hacemos para demostrar que se pueden
utilizar las tres clases en un mismo programa.
// Archivo todovehi.cpp
#include <iostream.h>
#include "vehiculo.h"
#include "carro.h"
#include "camion.h"
int main()
{
vehiculo monociclo;

monociclo.inicializa(1, 12.5);
cout << "El monociclo tiene " << monociclo.obtiene_llantas() << " llantas.\n";
cout << "La capacidad del monociclo es " << monociclo.llanta_carga()
<< " libras por llanta.\n";
cout << "El monociclo pesa " << monociclo.obtiene_peso() << " libras.\n\n";

car sedan;
sedan.inicializa(4, 3500.0, 5);
cout << "El sedan transporta " << sedan.pasajeros() << " pasajeros.\n";
cout << "El sedan pesa " << sedan.obtiene_peso() << " libras.\n";
cout << "La capacidad por llanta del sedan es " << sedan.llanta_carga()
<< " libras or llanta.\n\n";

camion semi;
semi.inicializa(18, 12500.0);
semi.ini_camion(1, 33675.0);
cout << "El semi pesa " << semi.obtiene_peso() << " libras.\n";
cout << "La eficiencia del semi es " << 100.0 * semi.eficiencia() << " por ciento.\n";

return 0;
}
Los archivos de cabecera para las tres clases están incluidas en las líneas 4 a la 6 así
que el programa puede utilizar los componentes de las clases. Observe que las
implementaciones de las tres clases no están aquí a la vista y no es necesario, esto
permite al código ser utilizado sin tener acceso al código fuente para la
implementación de las clases, sin embargo los archivos de cabecera de definición
deben estar disponibles. En éste programa de ejemplo solo se ha declarado un objeto
de cada clase pero debe quedar claro que se puede declarar cuantos objetos sean
necesarios en el programa. El resultado de la ejecución del programa es:
El monociclo tiene 1 llantas.
La capacidad del monociclo es 12.5 libras por llanta.
El monociclo pesa 12.5 libras.

El sedan transporta 5 personas


El sedan pesa 3500 libras.
La capacidad por llanta del sedan es 875 libras por llanta.
El semi pesa 12500 libras.
La eficiencia del semi es 72.9291 por ciento.

Uso del enunciado #ifndef


Regresando al archivo llamado vehiculo.h vemos las directivas al preprocesador
definidas en las líneas 3, 4 y 18 y es tiempo de explicarlas. Cuando definimos la clase
derivada carro, se nos solicitaba proveerla con la definición completa de la interfaz a
la clase vehiculo ya que carro es una clase derivada de vehiculo y debe conocer
todo respecto a la clase base. Hacemos ésto incluyendo la clase vehiculo en la clase
carro y entonces la clase carro puede ser compilada. La clase vehiculo debe ser
incluida en el archivo de cabecera de la clase camion por la misma razón.
Respecto al archivo todovehi.cpp debemos informarle de los detalles de las tres
clases, así que los tres archivos de cabecera deben ser incluidos, pero esto conduce a
un problema. Cuando el preprocesador llega a la clase carro incluye la clase vehiculo
porque así esta indicado en el archivo de cabecera de la clase carro pero como la
clase vehiculo fué incluida en la línea 4 de todovehi.cpp dá como resultado que la
clase vehiculo sea incluida dos veces. Ante esta situación el sistema no permite una
redeclaración de una clase. Permitimos la doble inclusión del archivo y al mismo
tiempo prevenimos la doble inclusión de la clase construyendo un puente utilizando la
palabra VEHICULO_H. Si la palabra yá fué definida, la declaración es ignorada, pero si
la palabra no ha sido definida, la declaración es incluida y entonces es definido
vehiculo.h. El resultado final es la inclusión, una sola vez, de la clase vehiculo aún y
cuando el archivo vehiculo.h haya sido incluido dos veces.

S-ar putea să vă placă și