HEREDITARIEDAD Y POLIMORMISMO

HEREDIETARIEDAD

Una clase puede heredar las características de otra. En C++ la clase heredada se denomina clase fundamental la clase heredadora clase derivada.
En C++ los elementos de una clase se subdividen en tres categorías:
- Públicos (palabra llave public)
- Privados (palabra llave private)
- Protegidos (palabra llave protected).
Un elemento es publico cuando se pude acceder al mismo desde cualquier otra función. A un elemento privado o protegido, sin embargo, solo pueden acceder las funciones elemento de la clase o funciones friend (las cuales se verán más adelante).
Cuando una clase hereda otra todos los elementos privados de la clase fundamental son inaccesibles a la clase derivada.

class clase_derivada: <acceso> clase_base

En este caso <acceso> solo pude ser private o public. Si se omite, el acceso por defecto es public.
Cuando el acceso es public todos los elementos protected de la clase fundamental permanecen protected en la clase derivada. Si el acceso es private todos los elementos public o protected de la clase fundamentales se convierten en elementos private de la clase derivada.

 

  • class X
  • {

  • int i;
    int j;
    public:
    void get_ij(void);
    void put_ij(void);
};
  • class Y:public X
  • {

  • int k;
    public:
    int get_k(void);
    void make_k(void);
};

En este caso la clase Y deriva de la clase X y los elementos de Y pueden acceder a las funciones public de X get_ij() y put_ij(), pero no a las variables i o j que son privadas de la clase X. La clase derivada tiene acceso a los elementos de la clase base cuando estos son protected.

 

  • class X
  • {

  • protected:
    int i;
    int j;
    public:
    void get_ij(void);
    void put_ij(void);
};
  • class Y:public X
  • {

  • int k;
    public:
    int get_k(void);
    void make_k(void);
};

Ahora Y tiene acceso a las variables i,j que a su vez permanecen inaccesibles al resto del programa. Cuando se define un elemento como privat el acceso es heredado por la clase derivada.

CONSTRUCTORES Y DESTRUCTORES EN CLASES DERIVADAS

Dado que el polimorfismo del C++ se basa esencialmente en las clases derivadas es importante analizar el comportamiento de los constructores y destructores.
Tanto una clase fundamental como una derivada pueden incluir un constructor (en caso de hereditariedad múltiple todas las clases puede incluir constructores).
Cuando una clase derivada contiene un constructor, el constructor fundamental es ejecutado antes que el correspondiente de la clase derivada. Obsérvese por ejemplo el siguiente programa:

 

  • #include <iostream.h>
    class Base
  • {

  • public:
    Base()
    {

  • cout << "\nBase generada\n";}
    }
 };
  • class D_classel : public Base
  • {

  • public:
    D_classel()
    {

  • cout << "D_classel generada\n";
    }
 
};
  • main(void)
  • {

  • D_classel dl;
    //despues del constructor no se ejecuta ninguna instrucción
    return O;
  • }
 

El programa crea un objeto de tipo D_clase1 y visualiza el siguiente resultado:

  • Base generata
    D_classel generata

En este caso d1 es un objeto de tipo D_clase1, derivado de la clase Base. Por tanto cuando se crea d1, se ejecuta primero el constructor Base() y después el D_clase1(). Es lógico que ello sea así, es decir que los constructores se ejecuten en el mismo orden que las derivaciones.
Otro aspecto a observar es que en el momento que se destruye una clase fundamental se destruyen las clases derivadas. Debido a esto es necesario llamar a los destructores de las clases derivadas antes que los de la clase fundamental pues de hacerse a la inversa sería llamado un destructor después de haber sido destruido. Para comprender lo dicho véase el siguiente ejemplo:

 

  • #include <iostream.h>
    class Base
  • {

  • public:
    Base()
    {

  • cout << "\nBase generada\n";
    }

~Base()

  • {
    cout << "Base destruida\n\n";)
    }
 
};
  • class D_classel : public Base
  • {

  • public:
    D_classe1()
    {

  • cout << "D_classe1 generada\n";
    }

~D_classe1()

  • {
    cout << "D_classe1 destruida \n";
    }
 
};
  • main(void)
  • {

  • D_classe1 d1;
    cout << "\n";
    return O;
  • }
 

El resultado es el siguiente:

  • Base generada
    D_classe1 generada
    D_classe1 distruida
    Base distruida

Como se sabe, es posible utilizar una clase derivada como clase fundamental para la creación de una derivada. En este caso se ejecutan los constructores en el orden de la derivación y los destructores en el orden inverso.
Considérese el siguiente programa donde se utiliza D_clase2 que deriva de D_clase1 y esta a su vez de la clase Base:

 

  • #include <iostream.h>
    class Base
  • {

  • public:
    Base()

  • {
    cout << "\nBase generada\n";
    }

~Base()

  • {
    cout << "Base destruida\n\n";
    }
 
};
  • class D_classel : public Base
  • {

  • public:
    D_classe1()

  • {
    cout << "D_classe1 generada\n";
    }

~D_classe1()

  • {
    cout << "D_classe1 destruida\n";
    }
 
};
  • class D_classe2 : public D_classel
  • {

  • public:
    D_classe2()

  • cout << "D_classe2 generada\n";

~D_classe2()

  • {
    cout << "D_classe2 destruida\n";
    }
 
};
  • main(void)
  • {


  • D_classel d1;
    D_classe2 d2;
    cout << "\n";
    return O;
  • }
 

El resultado es el siguiente:


  • Base generada
    D_classe1 generada

    Base generada
    D_classe1 generada
    D_classe2 generada

    D_classe2 destruida
    D_classe1 destruida
    Base destruida

    D_classe1 destruida
    Base destruida

CLASES FUNDAMENTALES MULTIPLES

Cuando se crea un tipo derivado es posible especificar más clases fundamentales. A tal fin se recurre a una lista de clases heredadas separadas por comas.
Considérese el siguiente programa:

 

  • #include <iostream.h>
    cLass Base1
  • {

  • public:
    Base1()

  • {
    cout << "\nBasel generada\n";
    }

~Base1()

  • {
    cout << "Basel destruida\n\n";
    }
 
};
  • c1ass Base2
  • {

  • pub1ic: Base2()

  • {
    cout << "Base2 generada\n";
    }

~Base2()

  • {
    cout << "Base2 destruida\n";
    }
 
};
  • // derivación de clases diferentes
    class D_classe1 : public Base1, public Base2
  • {

  • public:
    D_classe1()

  • {
    cout << "D_classe1 generada\n";
    }

~D_c1asse1()

  • {
    cout << "D_classe1 destruida\n";
    }
 
};
  • main(void)
  • {

  • D_c1assel d1;
    cout << "\n";
    return O;
  • }
 

En este programa D_clase1 deriva de Base1 y de Base2.
El resultado es:

  • Base1 generada
    Base2 generada
    D_classe1 generada

    D_classe1 destruida
    Base2 destruida
    Base1 destruida

Como de puede observar en caso de clases fundamentales múltiples los constructores son llamados en el orden de izquierda a derecha. Los destructores de derecha a izquierda