Herencia

Como se dijo anteriormente, la herencia es la característica que permite crear nuevas clases (clases derivadas, descendiente, clases hijas o subclases) a partir de una ya existente (Clase Base, ascendiente, clase padre o superclase).

Una clase puede heredar las características de otra clase y esta a su vez de una tercera (y así sucesivamente) ver figura:

Al esquema anterior se le denomina "Jerarquía de Clases".


Tipos de Herencia:

Existen dos tipos:

  1. Herencia Simple: Cada clase hereda de una única clase. En otras palabras, una clase tiene un solo ascendiente, sin embargo, cada clase base puede tener muchas clases derivadas.

    Ejemplo:


  2. Herencia Múltiple: En ella una clase tiene más de un descendiente o clase base.

    Ejemplo:


Acceso Protegido

En la declaración de una clase, además de las especificaciones de acceso public y private, se define el especificador protected que sólo se pueden acceder por los métodos de la misma clase y por los métodos de las clases derivadas de esta clase.

Declaración de una Clase Derivada

Sintaxis:

class Nombre (clase derivada): <especificador de acceso> 
                               Nombre de la clase base
{
     Cuerpo de la clase
}

El especificador de acceso puede ser a su vez:

Ejemplo:

class Mamifero:    public Animal
{    
		
      ...
}

Cuando una clase hereda de otra, la clase derivada hereda todos los atributos y métodos públicos de la clase base, por lo tanto en la clase derivada sólo se tiene que definir los atributos y métodos adicionales a ésta nueva clase.

Especificadores de Acceso

En la declaración de una clase derivada, como se ha mencionado, se debe anteponer al nombre de la clase base, la palabra reservada public, private o protected. Esto hace que el acceso a los atributos y métodos de la clase base sea según la siguiente tabla:


Funcionamiento de los Especificadores de Acceso


Especificadores de Acceso de la Clase

Accesibilidad desde la propia clase

Accesibilidad desde una clase derivada

Accesibilidad desde objetos externos

Public

Protected

No

Private

No

No


Ejemplo:

Grabar este ejemplo

#include<iostream.h>
class A { private: int a_pri; protected: int a_pro; public: int a_pub; }; class B: public A { int b; //private: public: void f_b(void); };
//equivale a: //class B //{ private: // int a_pri; // int b; // protected: // int a_pro; // public: // int a_pub; // void f_b(void); //};
void B::f_b(void) { b = a_pub; //valido b = a_pro; //valido //b = a_pri; //invalido }
class C:protected A { int c; public: void f_c(void); };
//equivale a: //class C //{ private: // int a_pri; // int c; // protected: // int a_pro; // int a_pub; // public: // void f_b(void); //};

void C::f_c(void) { c = a_pub; //valido c = a_pro; //valido //c = a_pri; //invalido }
class D:private A { int d; public: void f_d(void); };
//equivale a: //class D //{ private: // int a_pri; // int a_pro; // int a_pub; // int d; // public: // void f_b(void); //};

void D::f_d(void) { d = a_pub; //valido d = a_pro; //valido //d = a_pri; //invalido }
void main(void) { A AA; B BB; C CC;
int m;
m = AA.a_pub; //valido //m = AA.a_pro; //invalido //m = AA.a_pri; //invalido
m = BB.a_pub; //valido
//m = BB.a_pro; //invalido //m = BB.a_pri; //invalido //m = CC.a_pub; //invalido //m = CC.a_pro; //invalido //m = CC.a_pri; //invalido //m = DD.a_pub; //invalido //m = DD.a_pro; //invalido //m = DD.a_pri; //invalido

cout << m << endl; }

Nota: Si el especificador de acceso es omitido se considera por defecto private.

Ejemplo:

class D : A
{    ...
}
equivale a
class D : private A
{    ...
}

Miembros no Heredables

Una clase derivada no hereda los métodos constructores ni los métodos destructores.

Ejemplo de Herencia (sin constructores)

Grabar este ejemplo

#include<iostream.h>
const float PI = 3.141592;
class Circulo { float radio; public: void DefineRadio(float); float Radio(void); float Area(void); float Circunferencia(void); };
void Circulo::DefineRadio(float r) { radio = r; }
float Circulo::Radio(void) { return radio; }
float Circulo::Area(void) { return PI*radio*radio; }
float Circulo::Circunferencia(void) { return 2*PI*radio; }
class Cilindro:public Circulo { float altura; public: void DefineAltura(float); float Altura(void); float Volumen(void); float Superficie(void); };
void Cilindro::DefineAltura(float h) { altura = h; }
float Cilindro::Altura(void) { return altura; }
float Cilindro::Volumen(void) { return altura*Area(); }
float Cilindro::Superficie(void) { return 2*Area() + altura*Circunferencia(); }
class CilindroHueco : public Cilindro { float radioInterno; public: void DefineRadioInterno(float); float RadioInterno(void); float Volumen(void); float Superficie(void); };
void CilindroHueco::DefineRadioInterno(float ri) { radioInterno = ri; }
float CilindroHueco::RadioInterno(void) { return radioInterno; }
float CilindroHueco::Volumen(void) { return PI*Altura()*(Radio()*Radio() - Radio Interno()*RadioInterno()); //tener en cuenta que no se puede accesar a radio y altura }
float CilindroHueco::Superficie(void) { return 2*PI*( Radio()*Radio() - RadioInterno()*RadioInterno() ) + Altura()*Circunferencia() + Altura()*2*PI*RadioInterno(); }
void main (void) { Circulo Cir; Cilindro Cil; CilindroHueco CilH;
Cir.DefineRadio(1); cout << "Circulo :" << endl; cout << "radio =" << Cir.Radio() << endl; cout << "rea =" << Cir.Area() <<endl; cout << "circunferencia =" << Cir.Circunferencia() <<endl;
Cil.DefineRadio(1); Cil.DefineAltura(2); cout << "Cilindro :" << endl; cout << "radio =" << Cil.Radio() << endl; cout << "altura =" << Cil.Altura() << endl; cout << "volumen =" << Cil.Volumen() <<endl; cout << "superficie =" << Cil.Superficie() <<endl;
CilH.DefineRadio(1); CilH.DefineAltura(2); CilH.DefineRadioInterno(0.5); cout << "Cilindro Hueco :" << endl; cout << "radio externo =" << CilH.Radio() << endl; cout << "radio interno =" << CilH.RadioInterno() << endl; cout << "altura =" << CilH.Altura() << endl; cout << "volumen =" << CilH.Volumen() <<endl; cout << "superficie =" << CilH.Superficie() <<endl; }
/*resultado de la ejecución: Círculo : radio = 1 rea = 3.141592 circunferencia = 6.283184 Cilindro : radio = 1 altura = 2 volumen = 6.283184 superficie = 18.849552 Cilindro Hueco : radio externo = 1 radio interno = 0.5 altura = 2 volumen = 4.712388 superficie = 23.561939 */

Constructores de Clase Derivada

Como se mencionó, los constructores de las clases base no son heredadas por sus clases derivadas. Por lo tanto cuando se define una clase derivada, el constructor de esta clase debe invocar explícitamente al constructor de la clase base.

Sintaxis:

Grabar este ejemplo

class ClaseBase
{    ...
   public
     ClaseBase (argumentos);
     ...
}
ClaseBase :: (argumentos);
{    ...	//constructor de la claseBase
}
class ClaseDerivada { ... public ClaseDerivada (argumentos ClaseBase, argumentos ClaseDerivada); } ClaseDerivada ::: ClaseDerivada (argumentos ClaseBase, argumentos ClaseDerivada) : ClaseBase (Argumentos ClaseBase) { ... }
//Herencia con constructores
#include<iostream.h>
const float PI = 3.141592;
class Circulo { float radio; public: Circulo(float); void DefineRadio(float); float Radio(void); float Area(void); float Circunferencia(void); };
Circulo::Circulo(float r) //Constructor { radio = r; }
void Circulo::DefineRadio(float r) { radio = r; }
float Circulo::Radio(void) { return radio; }
float Circulo::Area(void) { return PI*radio*radio; }
float Circulo::Circunferencia(void) { return 2*PI*radio; }
class Cilindro:public Circulo { float altura; public: Cilindro(float, float); void DefineAltura(float); float Altura(void); float Volumen(void); float Superficie(void); };
Cilindro::Cilindro(float r, float h) : Circulo(r) { altura = h; } //Constructor llama a constructor de clase base
void Cilindro::DefineAltura(float h) { altura = h; }
float Cilindro::Altura(void) { return altura; }
float Cilindro::Volumen(void) { return altura*Area(); }
float Cilindro::Superficie(void) { return 2*Area() + altura*Circunferencia(); }
class CilindroHueco : public Cilindro { float radioInterno; public: CilindroHueco(float, float, float); void DefineRadioInterno(float); float RadioInterno(void); float Volumen(void); float Superficie(void); };
CilindroHueco::CilindroHueco(float r, float h, float ri) : Cilindro(r, h) { radioInterno = ri; }
void CilindroHueco::DefineRadioInterno(float ri) { radioInterno = ri; }
float CilindroHueco::RadioInterno(void) { return radioInterno; }
float CilindroHueco::Volumen(void) { return PI*Altura()*(Radio()*Radio() - RadioInterno()*RadioInterno()); //tener en cuenta que no se puede accesar a radio y altura }
float CilindroHueco::Superficie(void) { return 2*PI*(Radio()*Radio() - RadioInterno()*RadioInterno()) + Altura()*Circunferencia() + Altura()*2*PI*RadioInterno(); }
void main (void) { Circulo Cir(1); Cilindro Cil(1,2); CilindroHueco CilH(1,2,0.5);
cout << "Circulo :" << endl; cout << " radio = " << Cir.Radio() << endl; cout << " rea = " << Cir.Area() <<endl; cout << " circunferencia =" << Cir.Circunferencia() <<endl;
cout << "Cilindro :" << endl; cout << " radio = " << Cil.Radio() << endl; cout << " altura = " << Cil.Altura() << endl; cout << " volumen = " << Cil.Volumen() <<endl; cout << " superficie = " << Cil.Superficie() <<endl;
cout << "Cilindro Hueco :" << endl; cout << " radio externo = " << CilH.Radio() << endl; cout << " radio interno = " << CilH.RadioInterno() << endl; cout << " altura = " << CilH.Altura() << endl; cout << " volumen = " << CilH.Volumen() <<endl; cout << " superficie = " << CilH.Superficie() <<endl; }
/* resultado de la ejecución: Círculo : radio = 1 rea = 3.141592 circunferencia = 6.283184 Cilindro : radio = 1 altura = 2 volumen = 6.283184 superficie = 18.849552 Cilindro Hueco : radio externo = 1 radio interno = 0.5 altura = 2 volumen = 4.712388 superficie = 23.561939 */


Volver a contenidos AtrásSiguiente