Generalidades sobre el concepto de herencia en c++
Se entiende por herencia el proceso por el que un objeto puede tomar características de otro objeto1. La herencia se puede usar de dos formas:
1. Cuando una clase escrita no llega a cubrir las necesidades que exige un determinado problema, se
puede retocar el código cambiando las características que se requieren, e ignorando el resto. Esto
permite una programación rápida. Esto es una forma de reutilización del código.
2. Se expresa un determinado problema como una jerarquía de clases, donde existe una clase base de la
que se derivan otras subclases.
La interfaz de la clase base es común a todas las clases derivadas.
La herencia facilita la construcción de clases, una de las propiedades más interesantes de la filosofía de la POO.
Cuando una clase hereda de otra clase se denomina clase derivada, y a veces clase hija, subclase o clase
descendiente. La clase de la cual hereda recibe el nombre de clase base, en ocasiones también se la conoce
como clase padre, superclase o clase ascendiente
Cualquier clase puede ser una clase base. Es más una clase puede ser clase base para más de una clase derivada.
A su vez, una clase derivada puede ser clase base de otras clases.
Se recuerda que los elementos de una clase se pueden dividir en tres grupos:
- public: Accesibles desde cualquier función del programa.
- private: Sólo pueden acceder a ellos funciones miembros de la clase, o funciones afines.
- protected: Sólo pueden acceder a ellos las funciones miembro de la clase, de clases derivadas o lasfunciones afines.
Cuando se hereda, las clases derivadas reciben las características de la clase base, pudiendo añadir su
personalidad propia en forma de nuevas características, o modificando las heredadas. El compilador hace una copia de la clase base en la clase derivada, permitiendo al programador añadir o modificar miembros sin que la clase base sufra alteración alguna.
Hasta el momento se ha vendido como gran ventaja de los mecanismos de herencia la reutilización del código, que permite que un programador pueda utilizar una clase como clase base de otras nuevas clases, con la característica añadida que no hace falta comprender el fuente de la clase base, sólo hace falta saber lo que hace.
Pero la herencia tiene otra interesante característica, la extensibilidad. Esta propiedad permite que los
programas sean fácilmente ampliables, así de una clase base se pueden derivar varias clases que tengan un
interfaz común, pero su realización y las acciones que llevan a cabo sean diferentes, así el programa principal
controlará un grupo de estos objetos, puede utilizar una función miembro a cualquier objeto, pero el efecto será diferente, dependiendo de las subclases específicas.
Resumiendo las dos grandes ventajas del mecanismo de herencia en C++ son:
- Reutilización del código
- Extensibilidad
Dentro de los mecanismos de herencia se van a diferenciar dos tipos:
- La Herencia Simple. Una clase derivada tiene un sólo padre.
- La Herencia Múltiple. Una clase derivada hereda de más de una clase base.
Herencia Simple
Es cuando una clase derivada hereda de una única clase, es decir una clase derivada sólo tiene un padre o
ascendiente. Por su parte una clase base puede tener tantos descendientes como sean necesarios sin limitación alguna. Es un sistema jerárquico en forma arborescente, similar a la estructura de directorios de algunos sistemas operativos.
La forma general de la herencia en C++ es:
class <nombre_clase_derivada>: [<acceso>] <nombre_c
Herencia Múltiple
Una clase puede tener más de una clase base. Esto significa que una clase puede heredar de dos o más clases. A este fenómeno se le conoce como Herencia Múltiple.
La sintaxis de la herencia múltiple es una extensión de la utilizada para la herencia simple. La manera deexpresar este tipo de herencia es mediante una lista de herencia, que consta de las clases de las que se hereda separadas por comas. La forma general es:
class < nombre_clase_derivada > : < lista_de_herencia > {
// Cuerpo de la clase
};
Vamos a ilustrar la herencia múltiple con un sencillo ejemplo.
// Programa: Herencia Múltiple
// Fichero: HER_MUL1.CPP
#include <iostream.h>
class Base1 {
protected:
int b1;
public:
void Inicia_B1(int v) { b1=v; }
};
class Base2 {
protected:
int b2;
public:
void Inicia_B2(int v) { b2=v; }
int Ret (void) { return b2; }
};
class Der: public Base1, public Base2 {
public:
void print (void) { cout << "\nb1 = " << b1 << "\tb2 = " << Ret(); }
};
void main (void)
{
Der d;
d.Inicia_B2(78);
d.Inicia_B1(34);
d.print(); // Saca 34 y 78
}
La herencia múltiple, o derivación de clases con clases base múltiples, está permitida a partir de la versión 2.0 de C++
Este es un ejemplo muy sencillo en el que una clase, Der, hereda de otras dos clases Base1, Base2. En este programa no hay complicaciones de ningún tipo, y no es muy interesante.
En la herencia múltiple las reglas de inicio de los miembros son una extensión de los vistos en la herencia simple. De igual forma, los mecanismos de herencia de los miembros están gobernados por las declaraciones de private, protected y public en las clases.
El orden en el que se especifican las clases bases9 en la lista de herencia sólo afecta al orden en que se van a invocar los constructores, y destructores de las clases base desde los constructores y destructores de la clase derivada.
Vamos a ver a continuación otro ejemplo de herencia múltiple, en el que las clases tengan constructores.
// Programa: Herencia Múltiple
// Fichero: HER_MUL2.CPP
#include <iostream.h>
class A {
protected:
int a;
public:
A (int valor) {
cout << "\nConstructor de A.";
a=valor;
}
~A () { cout << "\nDestructor de A."; }
};
class B {
protected:
int b;
public:
B (int valor) {
cout << "\nConstructor de B.";
b=valor;
}
~B () { cout << "\nDestructor de B."; }
};
// C hereda de A y de B
class C: public A, public B {
public:
C(int v1, int v2) : B(v2), A(v1) {
cout << "\nConstructor de C.";
}
No está permitido que una misma clase base aparezca más de una vez en la lista de herencia. Es que sea una clase base directa más de una vez para una clase derivada, sin embargo pueden aparecer múltiples ocurrencias de la clase base de forma indirecta, a través de una clase base directa.
~C () { cout << "\nDestructor de C."; }
int operar (void) { return a*a+b*b; }
};
void main (void)
{
C obj(4, 5);
cout << "\n" << obj.operar();
};
La salida del programa anterior sería la siguiente:
Constructor de A
Constructor de B
Constructor de C
Destructor de C
Destructor de B
Destructor de A
De lo que se deduce que las clases bases se construyen en el orden en que aparecen en la declaración de C. Una vez que las clases han recibido los valores iniciales, se ejecuta el constructor de la clase derivada.
Mientras que ninguna de las clases base tenga constructor, o que todas las clases bases tengan un constructor por defecto, la clase derivada no tiene porque tener constructor.
De todas formas es una buena práctica de programación que todas las clases tengan un constructor para de esta forma contar con un mecanismo que permita pasar argumentos a los constructores de sus clases bases.
En cuanto a los destructores, decir que al igual que en la herencia simple, se llaman en orden inverso a la derivación.
Los mecanismos de herencia múltiple permiten al programador situar la información donde sea necesario. En contra, la herencia simple puede situar parte de los datos donde no se requieran.
No hay comentarios:
Publicar un comentario