La descarga está en progreso. Por favor, espere

La descarga está en progreso. Por favor, espere

Polimorfismo de ‘tipo’ (en la herencia)

Presentaciones similares


Presentación del tema: "Polimorfismo de ‘tipo’ (en la herencia)"— Transcripción de la presentación:

1 Polimorfismo de ‘tipo’ (en la herencia)
Pablo San Segundo (C-206)

2 Índice Overriding (especialización o redefinición)
Static bind (enlace estático) Dynamic bind (enlace dinámico) Casos prácticos

3 Overriding (especialización o redefinición)
Redefinición de una función en una clase derivada La función del mismo nombre queda oculta y sólo es accesible a través del nombre completo Polimorfismo distinto a la sobrecarga de funciones <objeto>.<clase_base>::<método> class Punto{ double x, y; public: //… void print(); }; <ref_objeto><clase_base>::<método> class Puntocol: public Punto{ char* color; public: //… void print(); //redefinición de función miembro }; TEST UNITARIO (*.cpp) void main(){ Puntocol p(5.0, 6.0, “azul”); p.print(); p.Punto::print(); }

4 Enlace estático El “tipo” de objetos, punteros o referencias es el declarado en código y no cambia Se dice que: se determina en tiempo de compilación Es el visto en el tema anterior (Herencia) Persona Empleado # nombre + verNombre() CUESTIÓN Un contenedor de tipos: 1- Referencia a Persona 2- Puntero a Persona ¿Podrá llamar a verNombre() de Persona cuando…? Contenga tanto Personas como Empleados

5 Enlace dinámico-generalidades (1/3)
El “tipo” de punteros y referencias es el tipo REAL de lo que se contiene en cada momento Se dice que: se determina en tiempo de ejecución EN CONSECUENCIA Dado que hay conversión implícita (UPCAST) en una relación de derivación pública, esto implica que: Es posible acceder a las funciones miembro de una clase derivada desde un puntero o referencia declarados como tipo base.

6 Enlace dinámico-sintaxis (2/3)
Funcionalidad Un puntero o referencia declarada como base que recibe un puntero a una clase derivada ejecutará la función miembro virtual de la clase derivada. De no existir, ejecutará la primera especialización que encuentre aguas arriba en la jerarquía ó, en su defecto, la propia función de la clase base. Palabra clave virtual : califica a las funciones miembro con enlace dinámico en la declaración de la clase. NO es necesario añadirlo en la redefinición de dichas fuciones en las clases derivadas Se suele incluir por estilo class Puntocol: public Punto{ //… virtual void print(); //'virtual' no obligatorio }; class Punto{ //…. virtual void print(); }; void main(){ Punto *p = new Puntocol(//…); p->print(); } CUESTIÓN ¿A qué función print() se llama?

7 Acerca de Guerreros y Magos
class Guerrero{ public: void pelear() const{ cout<<"pelea de guerrero"<<endl; } }; class Mago:public Guerrero{ cout<<"pelea de mago"<<endl; void pelea(const Guerrero& g){ g.pelear(); CUESTIÓN Modifique adecuadamente la jerarquía para que la función independiente pelear (…) consiga que los Guerreros y Magos luchen como lo que son.

8 Enlace dinámico-varios (3/3)
Las funciones independientes NO pueden declarase virtuales. La propiedad virtual se hereda siempre que la función tenga exactamente el mismo tipo de argumentos y valor de retorno (en caso contrario no se considerará redefinida). El nivel de acceso no afecta a las funciones virtuales (una función virtual privada en una clase derivada es accesible si es declarada como pública en la clase base). Su status es el de la clase Base RECORDATORIO Una función virtual aguas arriba siempre puede ser accedida explícitamente mediante el operador scope (::)

9 Ejemplos (1/3) class Base{ public:
virtual void myself(){cout<<"soy base"<<endl;} }; class Der1:public Base{ protected: void myself(){cout<<"soy derivada 1"<<endl;} class Der2: public Der1{ void myself(){cout<<"soy derivada 2"<<endl;} class Der3: public Der2{ void myself(){cout<<"soy derivada 3"<<endl;} void main() { Base base,*pBase; Der1 d1 Der2 d2 Der3 d3; pBase=&base; pBase->myself(); pBase=&d1; pBase=&d2; pBase=&d3; } CUESTIÓN ¿Existe enlace dinámico? void main() { Der3 d3; Base& rbase=d3; rbase.myself(); } CUESTIÓN I ¿Salida en pantalla? CUESTIÓN II ¿Y si myself() fuera privada en Der1?

10 Ejemplos (2/3) Ejercicio I
Implemente un caso de uso que demuestre el enlace dinámico para el método print() para un Estudiante Persona # name : string + virtual print(…) “<nombre>” Ejercicio II Implemente un caso de uso que cambie el nombre de un objeto Estudiante Adulto + print(…) + setName(…) “Adulto: <nombre>” Ejercicio III Sobrecargue el operador << adecuadamente para la jerarquia (redefina las funciones print() si fuera necesario) Compruebe que el nivel de permiso no afecta a las funciones virtuales. Estudiante + print(…) “ Estudiante: Adulto: <nombre>”

11 Ejemplos (3/3): flota de vehículos
Cuestión I* Defina fill() convenientemente para que tome los datos por teclado Vehiculo +virtual void print(ostream&) +virtual void fill() + friend ostream& operator <<(ostream &o, const Vehiculo &ve) Cuestión II* Defina print(…) convenientemente Cuestión III Razone acerca de la necesidad de destructores y la liberación de recursos TEST UNITARIO (main.cpp) void main(){ Vehiculo *flota[NUM_VEHICULOS]; int seleccion=0; for(int i=0;i<NUM_VEHICULOS;i++){ cout<<"Seleccione tipo del vehiculo "<<i<<":\n"; cout<<"(1-Vanette, 2-Coche): "; while((seleccion<1)||(seleccion>2))cin>>seleccion; switch(seleccion){ case 1:flota[i]=new Vanette; break; case 2:flota[i]=new Coche; } seleccion=0; flota[i]->fill(); cout<<"\n Estos son los vehiculos introducidos:\n"; for(int i=0;i<NUM_VEHICULOS;i++) cout<<i<<":"<<*flota[i]; Coche # char* marca # char* modelo +void print(ostream&) + void fill() Vanette - int tara +void print(ostream&) + void fill()

12 Ejemplos (4/4): magos y espadas
Cuestión I Coloque el calificativo de enlace dinámico para la función pelear(…) en el lugar más adecuado Ejercicio Sobrecarque el operador texto (<<) para Personaje. Haga las modificaciones oportunas en el resto de clases

13 Enlace dinámico para destructores
Declaración virtual para el destructor No aplica a constructores REGLA: Se declara siempre el destructor virtual en una clase base susceptible de ser derivada Vehiculo +virtual void print(ostream&) +virtual void fill() + virtual ~ Vehiculo() void main(){ //… //liberación de espacio en memoria de la flota for(int i=0;i<NUM_VEHICULOS;i++) delete flota[i]; } En el ejemplo: si flota[i] apunta a una Vanette Sin destructor virtual en Vehiculo: Se llama sólo al destructor de la base Con destructor virtual en Vehiculo: Se llama ordenadamente (primero-el-más-profundo) a los destructores de la jerarquía

14 Clases Abstractas- Funciones Virtuales Puras (1/2)
virtual <tipo> <id_funcion> <argumentos> = 0 Una función virtual pura se declara en la clase base Obliga a redefinirse en las clases derivadas En caso contrario se hereda como función virtual pura La clase que contiene a una función virtual pura se denomina clase abstracta

15 Clases Abstractas- Funciones Virtuales Puras (2/2)
No se permiten crear objetos de una clase abstracta Sí se pueden declarar punteros o referencias a la clase base, precisamente para implementar el mecanismo de enlace dinámico por el usuario La generalización / abstracción es una herramienta fundamental en el diseño OO A pesar de la aparente paradoja de conducir al diseño e implementación de clases que no van a poder ser instanciadas Nota: Es frecuente el uso del acrónimo ADT (Abstract Data Type) para denominar a las clases abstractas

16 Ejemplo I: Jerarquía de Vehículos
CUESTION I Complete el diseño de la jerarquía de vehículos anterior seleccionando adecuadamente funciones virtuales puras en la clase Vehiculo. Vehiculo +virtual void print(ostream&)=0 +virtual void fill()=0 + virtual ~ Vehiculo() CUESTION II ¿Se puede implementar el constructor como abstracto? virtual ~ Vehiculo() = 0 EJERCICIO Compruebe que se cumplen todas las propiedades descritas para las funciones virtuales puras y las clases abstractas

17 Ejemplo II: clases “interfaz” (1/2)
<<interface>> IVehiculo +virtual string getModelo()=0 +virtual string getMarca()=0 +virtual int getId()=0 DatosVehiculo + printDatos(//…) realizes / implements ID #int id Vehiculo #string marca #string modelo EJERCICIO Diseñe e implemente un acceso OO a la jerarquía para mostrar el estado de cualquiera de sus vehículos

18 Ejemplo II: clases “interfaz” (2/2)
EJERCICIOS Diseñe e implemente una arquitectura para poder ejecutar de manera transparente dos algoritmos distintos que generen la serie de fibonacci. Implemente, asimismo, el caso de uso. <<interface>> IFibo + virtual int fibo(int n)=0 FiboA FiboB + int fibo(int n) Alg IFibo* +fibo(int n) contiene void main(){ IFibo* p= new FiboA(); Alg miAlg(p); cout<<"sol:"<<miAlg.fibo(10); delete p; }

19 Ejemplo III: Juego de estrategia

20 Caso particular: definición de una función pura (1/2)
Es posible definir un comportamiento para una función virtual pura Sólo puede ser llamada mediante enlace estático class Vehiculo{ public: virtual void print() const =0; }; //definición de función virtual pura  inline void Vehiculo::print()const { cout<<"soy un vehiculo"<<endl; } class Coche:public Vehiculo{ virtual void print() const{ cout<<"soy un coche"<<endl; CUESTIÓN ¿Cuál es la principal diferencia si se hubiera definido la función print() como virtual y no como virtual pura? CLIENTE int main(){ Coche myc; myc.print(); //llamada a función por defecto myc.Vehiculo::print();   }

21 Aplicación-de Aviones y Vuelos (2/2)
class Avion{ public: virtual int volar()=0; }; class Airbus:public Avion{ int volar(){ cout<<"vuelo como Airbus generico"<<endl; return 0; } class Airbus303: public Airbus{ //Línea de desarrollo interrumpida //En este momento se desconoce la forma //de volar de este modelo

22 ¡Programe todos los ejemplos!
RESUMEN Enlace dinámico Clases abstractas Ejemplos ¿PREGUNTAS? ¡Programe todos los ejemplos!


Descargar ppt "Polimorfismo de ‘tipo’ (en la herencia)"

Presentaciones similares


Anuncios Google