Unida dad 4 H ncia y Jeraarquíaa de Heren Claases Introoducción mo es de nuestro conoccimiento púúblico la heerencia es el proceso ppor el cual podemos p Com dispooner de bieenes que haayan pertennecido a otrra persona, de maneraa análoga see da este proceeso en la pprogramacióón y es preecisamente este aspeccto que se consideraráá en esta unidaad. H 4.1. Herencia Sin duda d es la caaracterísticaa más potennte de la proogramación orientada a objetos, deespués de las clases. c Donnde, la herrencia es el proceso de crear nuevas n clases, llamadaas clases derivvadas, a parttir de una exxistente clase denominnada clase base. Básiccamente see afirma quue la heren ncia se apllica para exxtender y rreutilizar el e código existtente. De essta forma loos objetos se s pueden cconstruir dee modo incrremental a partir de otross objetos, abbriendo el camino para compartir código c y esttructura de datos. La heerencia pueede ser simpple o múltiplle. 4.2. Jerarquía J d Clases de Surgge fundamenntalmente de d la derivacción de classes que se producen, p een principioo siempre se paarte de una clase base denominadda padre, dee la cual see pueden creear clases derivadas d que se s conocen como hijoss, estos a suu vez pueden llegar a constituirsee en padress de otras clasees derivadass, conformánndose de essta forma la jerarquía de d clases. Base Derivadaa 1 D Derivada 1.11 Derivadaa 2 D Derivada 1.22 D Derivada 1.11.1. U.S..B. – Progra ramación IIII Páágina 46 4.3. Control de Accesos a la Clase Base En realidad al establecer el acceso que tendrá cada clase derivada lo que se especifica es la cantidad de elementos de la clase base que serán heredados por la clase derivada. La sintaxis en lenguaje C++ para establecer la derivación de una clase base es: class nombre_clase_base { private : //opcional . . . protected : . . . public : . . . }; class nombre_clase_derivada:tipo_de_acceso { ......................... }; Donde el tipo de acceso puede ser: public, private y protected, y dependiendo de esto se determinará los elementos de los cuales podrá disponer la clase derivada. Estos se presentan de manera esquemática, así: Acceso a los Miembros de la Clase Base Private Public Protected SI SI SI Clase base NO SI SI Clase derivada tipo public NO SI NO Clase derivada tipo private NO SI SI Clase derivada tipo protected NO SI NO Clase derivada tipo public desde programa principal NO SI NO Clase derivada tipo private desde programa principal NO SI NO Clase derivada tipo protected desde programa principal En base a estos principios se guían las herencias simples y múltiples. 4.4. Herencia Simple. La herencia simple se realiza tomando una clase existente y derivando nuevas clases de ella. U.S.B. – Programación III Página 47 Ejercicio: Defina los esquemas para definir la herencia entre estudiante y calificaciones. #include <iostream.h> #include <conio.h> #include <stdio.h> //clase base o padre class estudiante { long int ru; char nom [20] ; //Almacenar el nombre del estudiante char ape[30]; char dir[25]; char tel[7]; char celu[8]; public : void introduce( ) ; void muestra(); }; void estudiante:: introduce ( ) { cout<<endl<<”R.U.: ”; cin >>ru; cout<<”Nombres: ”; gets(nom) ; cout<<”Apellidos: ”; gets(ape) ; cout<<”Dirección: ”; gets(dir) ; cout<<”Telefono: ”; gets(tel) ; cout<<”Celular: ”; gets(celu) ; } void estudiante:: muestra( ) { cout<<endl<<”Estos son los datos del estudiante: ”; cout<<endl<<”R.U.: ”<<ru; cout<< endl<<”Nombres: ”<<nom ; cout<< endl<<”Apellidos: ”<<ape ; cout<< endl<<”Dirección: ”<<dir ; cout<< endl<<”Telefono: ”<<tel ; cout<< endl<<”Celular: ”<<celu ; } //clase derivada o hija de estudiante class calificaciones_sis507: public estudiante { int nota; public : void asigna( ){ cout<<endl<<”Nota: ”; cin>>nota;} int lanota() { return nota;} }; U.S.B. – Programación III Página 48 void main( ) { calificaciones_sis507 alumno; int n; alumno. introduce ( ); alumno.asigna( ); n =alumno.lanota( ); alumno.muestra( ); cout<<"La nota es: "<<n; getch( ); } 4.5. Constructores y destructores en herencia Los constructores y destructores de la clase base no se heredan por clases derivadas. En su lugar, los constructores de las clases hijas deben contener información de parámetros de los constructores de la clase base. La llamada a un constructor de una clase base se hace del mismo modo que las llamadas a los constructores de los miembros objeto. El nombre de la clase base se da seguida por la lista de parámetros del constructor: cabecera función : nombre_clase_base ( a1, a2, . . . ) lista de argumentos Es posible que una clase padre y otra hija tengan cada una su función de construcción. Cuando una clase derivada contiene un constructor, se ejecuta el constructor base antes de ejecutar el constructor de la clase derivada. class Base { public : Base ( ) { cout << “\n La clase Base ha sido creada” ; } }; class Derivada : public Base { public : Derivada ( ) { cout << “La clase derivada ha sido creada” ; } }; void main ( ) { Derivada der ; } El programa muestra: La clase Base ha sido creada. La clase Derivada ha sido creada. U.S.B. – Programación III Página 49 La función de destrucción de una clase hija se ejecuta antes que la de la clase padre. Esto es así ya que la destrucción de la clase padre implica la destrucción de la hija, así que el destructor de ésta debe ser ejecutado antes de ser destruido. 4.6. Herencia múltiple La herencia múltiple consiste en la posibilidad de una clase de heredar más de una clase a la vez. Por ejemplo: class A { // clase base o padre A . . . }; class B { // clase base o padre B . . . }; class AB : public A, public B { // AB herencia de A y de B ... }; Si la clase X tiene un constructor con parámetros, éstos se pueden pasar a cada clase base, como se indica a continuación: AB : : AB { ( int n = 0, float x = 0, char car = ‘A’ ) : A ( n, car ), B ( n, x ) { ... } La creación de un objeto de clase AB hace que los tres constructores de A, B y AB sean llamados en este orden: //clase Base1 class Base1 { protected : int b1 ; public : void set ( int i ) { b1 = i ;} }; //clase Base2 class Base2 { int b2 ; U.S.B. – Programación III Página 50 public : void set ( int i ) { b2 = i ; } int leer ( ) { return b2 ; } }; //hereda de Base1 y de Base2 class Derivada : public Base1, private Base2 { public : void imprimir ( ) { printf ( “b1 = %d y b2 = %d”, b1, leer ( ) ); } }; 4.7. Ejemplos Sencillos de Herencia. 1. /* PROGRAMA SENCILLO DE HERENCIA */ # include "stdio.h" # include "iostream.h" # include "conio.h" // Clase Base class Base{ protected: int a; public: void inicializaB(int iniA){a=iniA;} void muestraB(){cout<<"Elemento de la clase Base "<<a<<endl;} }; // Clase Derivada class Derivada:public Base{ int da; public: void inicializaD(int iniA){da=iniA;} void operator!(); void muestraD() { cout<<"Elemento de la clase Derivada "<<da<<endl; } }; void Derivada::operator!() { da=57; a=75; U.S.B. – Programación III Página 51 } void main() { Derivada obD; //Declarando un objeto derivado clrscr(); obD.inicializaB(4); obD.inicializaD(5); obD.muestraB(); obD.muestraD(); !obD; obD.muestraB(); obD.muestraD(); getch(); } 2. // Herencia con constructores # include "stdio.h" # include "iostream.h" # include "conio.h" // Clase Base class Base{ int a; public: Base(int iniA){a=iniA;} void muestraB(){cout<<"Elemento de la clase Base "<<a<<endl;} }; // Clase Derivada class Derivada:public Base{ int da; public: Derivada(int iniA,int iniDA):Base(iniA) { da=iniDA; cout<<"Constructor de la clase Derivada "; } void muestraD() { cout<<"Elemento de la clase Derivada "<<da<<endl; muestraB(); } }; void main() { U.S.B. – Programación III Página 52 clrscr(); Derivada obD(15,7); obD.muestraB(); obD.muestraD(); getch(); } Ejercicios Propuestos 1. Represente la clase Animal mediante las relaciones de herencia, cree al menos dos clases derivadas. 2. Implemente la clase Teatro e incluya la representación de herencia múltiple. 3. Diseñe un programa en el que incluya relaciones de herencia, y constructores para representar a los arreglos. U.S.B. – Programación III Página 53