Está en la página 1de 6

1

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 diferencie 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 return llantas;


}
#include "vehiculo.h"
// retorna el peso del vehiculo
// inicializa a cualquier dato deseado float vehiculo::obtiene_peso()
void vehiculo::inicializa(int in_llantas, float in_peso) {
{ return peso;
llantas = in_llantas; }
peso = in_peso;
} // retorna el peso en cada llanta
float vehiculo::llanta_carga()
// obtiene el numero de llantas del vehiculo {
int vehiculo::obtiene_llantas() return peso/llantas;
{ }
2

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 utilizándola 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
{
3
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 superclase 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.
4

// Archivo carro.cpp pasajeros_carga = personas;


#include "carro.h" llantas = in_llantas;
void carro::inicializa(int in_llantas, float in_peso, int peso = in_peso;
personas) }
{ int carro::pasajeros(void){ return pasajeros_carga; }

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 public:


#ifndef CAMION_H void ini_camion(int cuantos = 2,
#define CAMION_H float max_carga = 24000.0);
#include "vehiculo.h" float eficiencia(void);
class camion : public vehiculo int pasajeros(void);
{ };
int pasajeros_carga; #endif
float flete;

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 max_carga) float camion::eficiencia(void){ return flete / (flete +
{ peso);}
pasajeros_carga = cuantos; int camion::pasajeros(void){ return 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";
5
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.
6

También podría gustarte