Informática II 1 Diego Fernando Serna RestrepoSemestre 2011/2.

Slides:



Advertisements
Presentaciones similares
Curso de java básico (scjp)
Advertisements

Métodos y parámetros.
Curso de java básico (scjp)
Programación Gráfica 8. Clases y objetos.
Clases en C++.
Definición de Clases y Variables de referencia.
Herencia en C#.
Lenguaje de programación Java
Ejemplo de Programa C++
Informática II Clase 12: Flujos Diego Fernando Serna Restrepo
Clases Extendidas La clase extendida hereda los campos y métodos de la clase de la cual extiende. La clase original se conoce como superclase y la clase.
Procedimientos y Funciones
Clase 3: Punteros y Referencias
Informática II Prof. Dr. Gustavo Patiño MJ
Informática II Prof. Dr. Gustavo Patiño MJ
Informática II Prof. Dr. Gustavo Patiño MJ
Informática II 1 Diego Fernando Serna RestrepoSemestre 2011/2.
Informática II 1 Diego Fernando Serna RestrepoSemestre 2011/2.
Informática II 1 Diego Fernando Serna RestrepoSemestre 2011/2.
Informática II 1 Diego Fernando Serna RestrepoSemestre 2011/2.
Informática II 1 Diego Fernando Serna RestrepoSemestre 2011/2.
Objetos y Clases en Java
Programación Orientada a Objetos en Java
Acciones y funciones Concepto
Herramientas para el acceso directo a memoria en C++
HERENCIA.
Tema 7: Polimorfismo Antonio J. Sierra. Índice Introducción. Sobrecarga de métodos. Objetos como parámetros. Paso de argumentos. Devolución de objetos.
Programación I Teoría VI: Recursividad
Herencia e Interfaces.
Programación Orientada a Objetos usando C++
Medio de tele-comunicación
Modificadores.
Polimorfismo Lenguajes de Programación II Corporación Universitaria del Caribe CECAR.
Lic. Rosemary Torrico Bascopé
Clases y objetos La unidad fundamental de programación OO son las clases. Conjunto de métodos y semántica Qué se va a hacer POO Clase: que define la implementación.
Tema 6: Clases Antonio J. Sierra.
 2003 Prentice Hall, Inc. All rights reserved. 1 Capítulo 6: Clases y Abstracción de Datos Índice del capítulo 6.1 Introducción 6.2 Estructuras 6.3 Clases.
PROGRAMACIÓN ORIENTADA A OBJETOS USANDO C++
Desarrollador Profesional de Juegos Programación III Unidad II Una clase thread para window.
Capitulo # 4 herencia PROGRAMACION III UNIVERSIDAD
Programación Orientada a Objetos usando CONSTRUCTORES DESTRUCTORES.
PROGRAMACIÓN ORIENTADA A OBJETOS USANDO C++
PROGRAMACIÓN ORIENTADA A OBJETOS USANDO C++. 2 PROYECTOS EN C++
Administración de Proyectos de desarrollo de Software Ciclo de vida de un proyecto Enfoque moderno Temas Componentes Directivas Declaraciones globales.
Sobrecarga de operadores
1 Asignación Dinámica de Memoria Agustín J. González Versión original de Kip Irvine ELO 329.
Manejo de Punteros y objetos en memoria dinámica en C++
Dinamismo y Contenedores Facultad de Ciencias Exactas y Naturales Universidad de Buenos Aires (C++ Avanzado) Depto. de Computación Algoritmos y Estructuras.
Elementos básicos del lenguaje
Programanción I Ing. Cristhian Garita Fonseca
Constructor  Un constructor es un método que inicia un objeto inmediatamente después de su creación. De esta forma nos evitamos el tener que iniciar.
Metodología de Programación Ayudantía 5 lelagos.ublog.cl 2009.
Informatica II1 Clases Extendidas La clase extendida hereda los campos y métodos de la clase que ha sido extendida. La clase original se conoce como superclase.
Sesión 09: Sobrecarga (1) /1 Circuitos Digitales III 2010/1 Circuitos Digitales III 2010/1 Circuitos Digitales III 2010/1 Informática II Universidad.
Sesión 11: Herencia (1) – herencia simple /1 Circuitos Digitales III 2010/1 Circuitos Digitales III 2010/1 Circuitos Digitales III 2010/1 Informática.
Funciones y Clases Amigas (Friend)‏ Miembros Estáticos (Static)
Detalles Generales sobre Java
Sesión 12: Herencia (2) – herencia múltiple /1 Circuitos Digitales III 2010/1 Circuitos Digitales III 2010/1 Circuitos Digitales III 2010/1 Informática.
Sesión 10: Sobrecarga (2) /1 Circuitos Digitales III 2010/1 Circuitos Digitales III 2010/1 Circuitos Digitales III 2010/1 Informática II Universidad.
1 Asignación Dinámica de Memoria Agustín J. González ELO 329.
INTRODUCCION A LA PROGRAMACION
Sesión 06: Clases y Objetos (2)
LENGUAJE “C” Programación.
6. Clases y Métodos..  6.1 Structs  6.2 Funciones  6.3 Namespaces  6.4 Clases.
Informática II 1 Diego Fernando Serna RestrepoSemestre 2011/2.
Programación orientada a objetos La programación orientada a objetos o POO (OOP según sus siglas en inglés) es un paradigma de programación que usa objetos.
Prof. Manuel B. Sánchez. Declaración de Objetos Una vez que la clase ha sido implementada se pueden declarar objetos como variables locales de métodos.
This y static. This Normalmente, dentro del cuerpo de un método de un objeto se puede referir directamente a las variables miembros del objeto. Sin embargo,
Prof. Manuel B. Sánchez. Es un mecanismo y uno de los pilares de la POO que permite definir nuevas clases a partir de otras preexistentes. La Herencia.
3.6 Manejo de E/S Estructuras En la creación de soluciones para algunos problemas surge la necesidad de agrupar datos de diferente tipo o de manejar datos.
Transcripción de la presentación:

Informática II 1 Diego Fernando Serna RestrepoSemestre 2011/2

C HISTE DEL D ÍA Informática II 2011/2 2

Z ONA DE PREGUNTAS 1.Cuando se llama el constructor de copia? 2.Qué es Poliformismo? 3.Que es el puntero this ? 4.¿Cómo se puede diferenciar entre la sobrecarga del operador prefijo y sufijo? Informática II 2011/2 3

C ONTENIDO Informática II 2011/2 4 Repaso 1 Herencia 2 Métodos ocultos 3 4 Funciones Virtuales

S OBRECARGADO DE FUNCIONES (P OLIMORFISMO ) Consiste en crear diferentes funciones con el mismo nombre, con el fin de ofrecer al usuario una manera más sencilla de recordar las funciones. //Algunos protototipos int funcion(int); int funcion(long, long); int funcion(long); /* El programa determina cual de las funciones “funcion” ha sido llamada, según los parámetros con que sea llamada la función*/ Informática II 2011/2 5

S OBRECARGADO DE LOS MÉTODOS DE LAS CLASES Los métodos de las clases también pueden ser sobrecargados como el resto de las funciones, su sintaxis es prácticamente igual. class Rectangulo { public: // función DibujarFigura() sobrecargada de la clase void DibujarFigura() const; void DibujarFigura(int unAncho, int unaAltura) const; private: int suAncho; int suAltura; }; Informática II 2011/2 6 void DibujarFigura() const; void DibujarFigura(int unAncho, int unaAltura) const;

I NICIALIZACIÓN DE LAS VARIABLES MIEMBRO Las variables miembro pueden ser inicializadas tanto en la etapa de inicialización de métodos, como en el cuerpo de éstos. Informática II 2011/2 7 //Etapa de inicialización Gato::Gato(): suEdad(5), suPeso(8) { //Cuerpo del constructor } //Nombre y parámetros del constructor

C ONSTRUCTORES DE COPIA Informática II 2011/2 8 La copia superficial es buena para casi todo tipo de variables; sin embargo, es muy fácil de romper cuando los miembros son punteros a objetos en el Heap.

C ONSTRUCTORES DE COPIA La solución para evitar problemas ocasionados por las copias superficiales, es usando los constructores de copia para que estos hagan la copia en diferentes espacios del Heap, realizando lo que se denomina como “Copia Profunda”. Informática II 2011/2 9

1 Cuando se pasa un objeto como argumento a una función o esta lo retorna, se hace una copia temporal de cada una de sus variables miembro. 2 Todo constructor de copia, toma como parámetro una referencia a un objeto de su misma clase. carro(carro &original); Informática II 2011/2 10 C ONSTRUCTORES DE COPIA

3 El objetivo del constructor de copia, es crear una copia exacta de cada variable miembro del objeto pasado como referencia (original). Este copia se denomina “superficial”. 4 Los constructores de copia superficiales funciona perfectamente cuando se trata de un objeto cuyas variables miembro no son punteros referenciados a variables u objetos alojados en el Heap (free store). 5 En algunas ocasiones se hace necesario definir personalmente un constructor de copia, que evite que se haga una copia errónea, donde se garantice la independencia de cada objeto con respecto a cada una de sus variables miembro (copia profunda). Informática II 2011/2 11 C ONSTRUCTORES DE COPIA

S OBRECARGADO DE LOS OPERADORES La sobrecarga de operadores quiere decir que se pueden redefinir algunos de los operadores existentes en C++ para que actúen de una determinada manera, definida por el programador, con los objetos de una clase creada por el mismo. La sobrecarga de operadores se emplea para declarar “como es que funciona” dicho operador cuando se utilizan sobre los objetos. Informática II 2011/2 12

S OBRECARGA DE OPERADORES El objetivo de la sobrecarga de operadores es simplificar al máximo el código a escribir, a cambio de complicar algo la definición de las clases. Una clase que disponga de operadores sobrecargados es una clase más compleja de definir, pero más sencilla e intuitiva de utilizar. Informática II 2011/2 13

S OBRECARGA DE OPERADORES La sobrecarga de un operador puede ser declarada de la siguiente forma: tipodeRetorno operator op (parametros); Informática II 2011/2 14 void operator ++ (); // Ejemplo de una declaración para el sobrecargado del operador ++ void operator ++ (); // Ejemplo de una declaración para el sobrecargado del operador ++ Void, int, char, … Palabra reservada Palabra reservada -, --, +, ++, =, ==, … Void, int, char, …

E JEMPLO S OBRECARGA DEL OPERADOR P REFIJO Informática II 2011/2 15 class contador{ private: int variable; public: contador(); //constructor de copia contador(contador& original); int getvariable() const; void setvariable(int _variable); void incrementar(); //sobrecarga el operador //preincremento (++i) void operator ++(); ~contador(); }; contador::contador():variable(0){} //constructor de copia contador::contador(contador& original){ variable=original.variable; } int contador::getvariable() const{ return variable; } void contador::setvariable(int _variable){ variable=_variable; } void contador::incrementar(){ ++variable; } //definición de la sobrecarga del operador preincremento (++i) void contador::operator++(){ ++variable; } //Destructor contador::~contador(){} using namespace std; contador mycontador(); int main() { mycontador.incrementar(); cout<<"incremento utlizando un metodo: " \ << mycontador.getvariable()<<endl; ++mycontador; cout<<"incremento sobrecargando el operador ++:" \ <<mycontador.getvariable()<<endl; return 0; } 0 1

Ahora lo que generalmente se desea es poder es retornar un objeto tipo contador, de este modo poder reasignarlo a otro objeto tipo contador. Informática II 2011/2 16 E JEMPLO S OBRECARGA DEL OPERADOR P REFIJO //definición de la operador preincremento (++i) contador contador::operator++(){ ++variable; contador temp; temp.setvariable(variable); return temp; } using namespace std; contador cont1; int main() { cont1.incrementar(); cout<<"cont1: " <<cont1.getvariable()<<endl; contador cont2=++cont1; cout<<"cont2: "<<cont2.getvariable()<<endl; return 0; } cont1: 1 cont2: 2

S OBRECARGADO DEL OPERADOR POSFIJO Declaración const Contador Contador::operator++(int flag) { Contador temp(*this); ++itsVal; return temp; } /* Notese el uso de la variable flag... dicha vble es declarada pero ¡¡nunca es utilizada!! */ Informática II 2011/2 17 flag tipo int tiene valor 0 y no se utiliza nunca, solo sirve como criterio de distinción frente al operador de preincremento.

S OBRECARGA DEL OPERADOR DE P OSTINCREMENTO 1 Creamos un objeto temporal copia del objeto original. 2 Modificamos el valor de la variable del objeto original. 3 Retornamos el objeto copia temporal. Informática II 2011/2 18 De este modo, el valor del objeto será modificado, pero en la expresión donde aparezca se tomará el valor antes de modificar.

E JEMPLO S OBRECARGA DEL OPERADOR P OSFIJO Informática II 2011/2 19 class contador{ private: int variable; public: contador(); //constructor de copia contador(contador& original); int getvariable() const; void setvariable(int _variable); void incrementar(); //sobrecarga el operador preincremento (++i) const contador& operator ++(); //sobrecarga del operador posincremento (i++) const contador operator ++(int flag); ~contador(); }; //Constructor contador::contador():variable(0){} //constructor de copia contador::contador(contador& original){ variable=original.variable; } int contador::getvariable() const{ return variable; } void contador::setvariable(int _variable){ variable=_variable; } void contador::incrementar(){ ++variable; } //definicion de la operador preincremento (++i) const contador& contador::operator++(){ ++variable; return *this; } //definicion del operador posincremento (i++) const contador contador::operator++(int flag){ //hace una copia del objeto contador temp(*this); ++variable; return temp; } using namespace std; contador cont1; //Ejemplo operador posincremento int main() { cont1.incrementar(); cout<<"incremento utlizando un metodo: "<< cont1.getvariable()<<endl; contador cont2=++cont1; cout<<"El valor de cont1 luego de preincremento "<<cont1.getvariable()<<endl; cout<<"El valor de cont2: "<<cont2.getvariable()<<endl; cont2=cont1++; cout<<"El valor de cont2: "<<cont2.getvariable()<<endl; cout<<"El valor de cont1 luego de posincremento: "<<cont1.getvariable()<<endl; return 0; } cont1: 1 cont1: 2 cont2: 2 cont1: 3

S OBRECARGA DE OPERADORES 1 Un operador puede estar sobrecargado o redefinido varias veces, de tal manera que actúe de un modo distinto dependiendo del tipo de objetos que tenga como argumentos de entrada. 2 Las ventajas de la sobrecarga de operadores terminan cuando se utiliza de modo que añade complejidad o confusión a los programas. Por ejemplo: no se deberá nunca utilizar el operador (-) para multiplicar matrices o el (+) para imprimir vectores. 3 Los únicos operadores de C++ que no se pueden sobrecargar son: El operador punto (.), El if aritmético (?:) El operador sizeof, El scope operator (::) puntero a miembro de un objeto (.*). Informática II 2011/2 20

O PERADORES B INARIOS son aquellos que requieren dos operandos, como la suma o la resta. Cuando se sobrecargan operadores en el interior se asume que el primer operando es el propio objeto de la clase donde se define el operador. Debido a esto, sólo se necesita especificar un operando como argumento. Informática II 2011/2 21

Informática II 2011/2 22 class contador{ private: int variable; public: contador(); contador(int _variable); //constructor de copia contador(contador& original); int getvariable() const; void setvariable(int _variable); void incrementar(); //sobrecarga el operador + contador operator +(const contador& other); ~contador(); }; contador::contador():variable(0){} contador::contador(int _variable): variable(_variable){} //constructor de copia contador::contador(contador& original){ variable=original.variable; } S OBRECARGANDO EL OPERADOR + int contador::getvariable() const{ return variable; } void contador::setvariable(int _variable){ variable=_variable; } void contador::incrementar(){ ++variable; } //definición del operador + contador contador::operator +(const contador& other){ contador temp; temp.setvariable(variable+other.getvariable()); return temp; } contador::~contador(){} using namespace std; //Ejemplo operador + int main() { contador cont1(5),cont2(6); contador cont3=cont1+cont2; cout<<"el valor de cont1 es: "<<cont1.getvariable()<<endl; cout<<"el valor de cont2 es: "<<cont2.getvariable()<<endl; cout<<"el valor de cont3 es: "<<cont3.getvariable()<<endl; return 0; } cont1: 5 cont2: 6 cont3: 11

Informática II 2011/2 23 S OBRECARGANDO EL OPERADOR = Qué pasa si el objeto cont1 tiene como variables miembro punteros que acceden a memoria dinámica? El objeto cont2 al ser de la misma clase que cont1 igualmente ya cuenta con espacio en memoria dinámica, luego solo basta con copiar el nuevo valor respectivo en dicho espacio. Qué pasa con los datos originales almacenados por cont2? int main() { contador cont1(5),cont2(6); cont2=cont1; cout<<"el valor de cont1 es: "<<cont1.getvariable()<<endl; cout<<"el valor de cont2 es: "<<cont2.getvariable()<<endl; return 0; }

Informática II 2011/2 24 S OBRECARGANDO EL OPERADOR = //sobrecarga el operador = const contador& operator =(const contador& other); //definicion del operador = const contador& contador::operator =(const contador& other){ if(this==&other){ return *this; } else{ variable=other.variable; } return *this; }

C ONTENIDO Informática II 2011/2 25 Repaso 1 Herencia 2 Métodos ocultos 3 4 Funciones Virtuales

H ERENCIA Diferentes tipos de objetos usualmente comparten características similares entre sí. La herencia permite generar nuevos tipos, tomando como base alguno ya implementado. También hace posible la implementación de jerarquías desde la generalización hasta la especialización de los objetos. Informática II 2011/2 26

La programación orientada a objetos permite a las clases heredar las características y los comportamientos de otras clases (variables miembro y los métodos). Adicionalmente C++, permite definir una clase modificando una o más clases ya existentes. Estas modificaciones consisten habitualmente en añadir nuevos miembros (variables o métodos) a la clase que se está definiendo, aunque también se puede redefinir variables o funciones miembro ya existentes. Informática II 2011/2 27 H ERENCIA

La clase de la que se parte en este proceso recibe el nombre de clase base, y la nueva clase que se obtiene se denomina clase derivada. Ésta a su vez puede ser clase base en un nuevo proceso de derivación, iniciando de esta manera una jerarquía de clases. Informática II 2011/2 28 H ERENCIA

C LASE B ASE A BSTRACTA De estas clases no se declara ningún objeto Su función es la de agrupar miembros comunes de otras clases que se derivarán de ellas. Por ejemplo, se puede definir la clase vehículo para después derivar de ella carro, moto, bicicleta, etc., pero todos los objetos que se declaren pertenecerán a alguna de estas últimas clases; no habrá vehículos que sean sólo vehículos. Informática II 2011/2 29 Son Clases que no tiene otra utilidad que la de ser clase base para otras clases se deriven de ella. La herencia presenta múltiples ventajas, como la posibilidad de reutilizar código sin tener que escribirlo de nuevo. Esto es posible porque todas las clases derivadas pueden utilizar el código de la clase base sin tener que volver a definirlo en cada una de ellas.

D ECLARACIÓN DE H ERENCIA Informática II 2011/2 30 Cuando se declara una clase, es posible indicar de donde va a heredar sus carácterísticas, y se declara de la siguiente manera: class claseDerivada : tipoDeAcceso claseBase Ejemplo: class perro : public animal { ……. } // Se genera la clase perro a partir de la clase animal

M ODIFICADOR DE ACCESO P ROTECTED Informática II 2011/2 31 Cuando un miembro de una clase es declarado como “protected”, se garantiza que dicho miembro puede ser accedido tanto para dicha clase como desde sus clases derivadas. Para el resto de los casos no podrá ser accedida directamente (como los miembros privados).

Informática II 2011/2 32 Cuando se usa herencia pública, se garantiza que todos sus miembros protegidos podrán ser accedidos desde las clases derivadas. Si un miembro es declarado como “private”, no podrá ser accedido por sus clases derivadas. Los miembros públicos seguirán siendo públicos en toda la línea de herencia. M ODIFICADOR DE ACCESO P ROTECTED

M ODIFICADORES DE A CCESO Informática II 2011/2 33

E JEMPLO H ERENCIA Informática II 2011/2 34 class vehiculo{ protected: int vel; bool on; public: vehiculo(); vehiculo(int _vel,bool _on); int getVel() const; void setVel(int _vel); ~vehiculo(); }; class bicicleta: private vehiculo{ private: int Ncambio; int pedalear; int Ndiscos; public: bicicleta(); void cambCambio(int _Ncambio); ~bicicleta(); }; //clase vehiculo vehiculo::vehiculo():vel(0),on(false){ cout<<"constructor clase base"<<endl; } vehiculo::vehiculo(int _vel,bool _on):vel(_vel),on(_on){ cout<<"constructor con argumentos clase base"<<endl; } int vehiculo::getVel() const { return vel; } void vehiculo::setVel(int _vel){ vel=_vel; } vehiculo::~vehiculo(){} //clase carro carro::carro():Ncambio(0),acelerar(0){ cout<<"constructor por defecto clase derivada"<<endl; } void carro::cambCambio(int _cambCambio){ Ncambio= _cambCambio; } carro::~carro(){} class carro: public vehiculo{ private: int Ncambio; int acelerar; public: carro(); void cambCambio(int _Ncambio); ~carro(); }; using namespace std; carro audi; int main() { //damos un valor a una variable miembro heredada audi.setVel(10); //accedemos a un metodo heredado cout<<audi.getVel()<<endl; return 0; } audi vel: 10

N OTAS : 1 Primero se debe crear la clase base, antes de tratar de crear clases que deriven de esta. 2 El número de variables miembro de una clase derivada es mayor o igual que el de la clase base. 3 Hay algunos elementos de la clase base que no pueden ser heredados: Constructores y destructores Funciones friend Funciones y datos estáticos de la clase Operador de asignación (=) sobrecargado Informática II 2011/2 35

C ONSTRUCTORES Y D ESTRUCTORES Cuando un objeto derivado es creado primero es llamado el constructor de la clase base y luego el propio. Informática II 2011/2 36 int vel; bool on; int vel; bool on; int Ncambio; int acelerar; int Ncambio; int acelerar; Parte vehículo Objeto carro Cuando un objeto es derivado y este se destruye, se llamará primero el destructor de este y posteriormente se llama automáticamente el destructor de la clase base. No es posible crear una clase derivada sin crear primero su porción de la clase base.

P ASAR ARGUMENTOS AL CONSTRUCTOR BASE Se pueden inicializar las variables miembro heredadas, llamando al constructor de la clase base desde la etapa de inicialización del constructor de la clase derivada así: Informática II 2011/2 37 carro(int _vel,bool _on); carro::carro(int _vel,bool _on): Ncambio(0), acelerar(0){ } vehiculo(_vel,_on),

R EDEFINICIÓN DE FUNCIONES Informática II 2011/2 38 Es posible que una clase derivada “sobreescriba” el funcionamiento de un método de su clase base, basta con redefinir nuevamente dicho método en la clase derivada. Para poder “sobreescribir ” un método es necesario que las firmas de ambas clases sean iguales Nota: Firma = a todo lo declarado en el prototipo de las funciones (incluyendo const) a excepción de su variable de retorno. int getVel() const; Firma Argumento de retorno

E JEMPLO R EDEFINICIÓN DE M ÉTODOS Informática II 2011/2 39 class vehiculo{ protected: int vel; bool on; public: vehiculo(); vehiculo(int _vel,bool _on); int getVel() const; void setVel(int _vel); ~vehiculo(); }; class carro: public vehiculo{ private: int Ncambio; int acelerar; public: carro(); carro(int _vel,bool _on); int getVel() const; void cambCambio(int _Ncambio); ~carro(); }; int vehiculo::getVel() const { cout<<"funcion getVel clase base"<<endl; return vel; } int carro::getVel() const{ cout<<"funcion getVel clase derivada"<<endl; return vel; } int main() { //damos un valor a una variable miembro heredada audi.setVel(10); //accedemos a un método heredado redefinido cout<<audi.getVel()<<endl; //acedemos al metodo de la clase base cout<<audi.vehiculo::getVel()<<endl; return 0; }

S OBRECARGAR V S R EDEFINIR Cuando se sobrecarga funciones, el nombre de la función permanece, pero los argumentos de entrada y de retorno pueden variar, al igual que la implementación. Cuando se redefine una función lo único que cambia es su implementación. El encabezado permanece igual (argumento de retorno y firma) en la clase base como en la derivada. Informática II 2011/2 40

C ONTENIDO Informática II 2011/2 41 Repaso 1 Herencia 2 Métodos ocultos 3 4 Funciones Virtuales

O CULTANDO LOS M ÉTODOS DE LA C LASE B ASE Si la clase base contiene varios métodos sobrecargados, es decir métodos con nombres iguales pero con argumentos e implementaciones diferentes, y redefinimos uno de esos métodos dentro de una clase derivada, todos los métodos dentro de la clase base que respondan al mismo nombre quedaran ocultos, es decir no se podrán acceder a través del objeto derivado. Informática II 2011/2 42

E JEMPLO Informática II 2011/2 43 class vehiculo{ protected: int vel; bool on; public: vehiculo(); vehiculo(vehiculo &V); vehiculo(int _vel,bool _on); void setVel(int _vel); int getVel() const; //sobrecarga metodo getVel int getVel(float other); int getVel(int other); virtual vehiculo* clonar(); virtual ~vehiculo(); }; class carro: public vehiculo{ private: int Ncambio; int acelerar; public: carro(); carro(int _vel,bool _on); int getVel() const; void cambCambio(int _Ncambio); ~carro(); }; carro audi(10,true); int main() { int a=5; float b=45.6; //solo podemos acceder a el método heredado redefinido audi.getVel(); audi.getVel(a); //para haceder a los demás métodos sobrecargados audi.vehiculo::getVel(); audi.vehiculo::getVel(a); audi.vehiculo::getVel(b); return 0; }

C ONVERSIONES ENTRE CLASE B ASE Y D ERIVADA 1 Es posible realizar conversiones o asignaciones de un objeto de una clase derivada a un objeto de la clase base. 2 Es decir se puede ir de lo más particular a lo más general, aunque en esa operación se pierda información, pues haya variables que no tengan a qué asignarse 3 Por el contrario las conversiones o asignaciones en el otro sentido, es decir de lo más general a lo más particular, no son posibles, porque puede suceder que no se disponga de valores para todas las variables miembro de la clase derivada. Informática II 2011/2 44

Informática II 2011/2 45 Objeto_claseBase= Objeto_claseDerivada; Objeto_claseDerivada= Objeto_claseBase; C ONVERSIONES ENTRE CLASE B ASE Y D ERIVADA Se puede hacer referencia a un objeto de la clase derivada con su dirección contenida en un puntero a la clase base. vehiculo *ptrV=new carro(30,true); carro *ptrC=new vehiculo();

En conclusión un puntero a la clase base puede almacenar la dirección de un objeto perteneciente a una clase derivada. Sin embargo, se aplicarán los métodos de la clase a la que pertenezca el puntero (base), no los de la clase a la que pertenece el objeto (derivada). El tipo del puntero utilizado para acceder a un método que se encuentra implementado en ambas clases (base y derivada), determinará cuál de los dos métodos llamar. Informática II 2011/2 46 C ONVERSIONES ENTRE CLASE B ASE Y D ERIVADA using namespace std; int main() { vehiculo *ptrV=new carro(30,true); cout getVel()<<endl; //se accede al metodo de la clase base return 0; }

C ONTENIDO Informática II 2011/2 47 Repaso 1 Herencia 2 Métodos ocultos 3 4 Funciones Virtuales

M ÉTODOS V IRTUALES Tenemos un problema cuando deseamos acceder al método de la clase derivada a través de un puntero de tipo clase base. Para lograrlo debemos definir el método como virtual dentro de la clase base. Para declarar una función como virtual basta con adicionar la palabra “virtual” al inicio de su prototipo. Informática II 2011/2 48 virtual par.retorno declaracionMetodo(parámetros entrada );

E JEMPLO M ÉTODOS V IRTUALES Informática II 2011/2 49 class vehiculo{ protected: int vel; bool on; public: vehiculo(); vehiculo(int _vel,bool _on); virtual int getVel() const; void setVel(int _vel); ~vehiculo(); }; class carro: public vehiculo{ private: int Ncambio; int acelerar; public: carro(); carro(int _vel,bool _on); int getVel() const; void cambCambio(int _Ncambio); ~carro(); }; int vehiculo::getVel() const { cout<<"funcion getVel clase base"<<endl; return vel; } int carro::getVel() const{ cout<<"funcion getVel clase derivada"<<endl; return vel; } using namespace std; int main() { vehiculo *ptrV=new carro(30,true); cout getVel()<<endl; //se accede al método de la clase derivada return 0; }

Si un método en cuestión es designado "virtual" en la clase base, se llamará a la función de la clase derivada (si existe). Si no es virtual, se llamará a la función de la clase base. El modificador virtual nos permite incluir un método en varios niveles de una jerarquía de clases con el mismo nombre pero con distinta definición. Una vez que un método es declarado como virtual, lo seguirá siendo en las clases derivadas, es decir, la propiedad virtual se hereda Informática II 2011/2 50 M ÉTODOS V IRTUALES

Por cada clase que utiliza métodos virtuales, se genera una tabla por parte del compilador denominada v-table, que contiene la información de cada uno de los métodos definidos como virtuales. Cada objeto creado de una clase que tenga una función virtual contiene un puntero oculto a la v-table de su clase. Mediante ese puntero accede a su v-table correspondiente y a través de esta tabla accede a la definición adecuada del método virtual. En el caso de que en esa clase no esté definido el método virtual en cuestión, el puntero de v-table apuntará a la función virtual de su clase base más próxima en la jerarquía, que tenga una definición propia de la función virtual. Informática II 2011/2 51 M ÉTODOS V IRTUALES

Esto quiere decir que buscará primero en la propia clase, luego en la clase anterior en el orden jerárquico y se irá subiendo en ese orden hasta dar con una clase que tenga definido el método buscado. Cuando el compilador llama el método virtual de la clase base, en vez del método de la case derivada, se dice que se presento un “Data Slicing”. Las funcionalidades de los métodos virtuales, solo pueden ser usadas cuando se trabaja con punteros o referencias de la clase base. Informática II 2011/2 52 M ÉTODOS V IRTUALES

S LICING O PARTICIÓN EN C ++ Informática II 2009/2 53 Las funcionalidad de las funciones virtuales, śolo pueden ser usadas cuando se trabaja con punteros o referencias de la clase base. Si a una función se le pasa un objeto por valor se dice que se genera un “slice”, pues no sobrescribirá ninguna de las funciones virtuales descartando así cualquier modificación de las clases derivadas.

C ONSTRUCTORES Y D ESTRUCTORES V IRTUALES Informática II 2009/2 54 Cuando se genera al menos un método virtual en la clase base, es indispensable nombrar el destructor como virtual, para garantizar así que primero se llame el destructor de la clase derivada y luego este se encargue de llamar al de la clase base. Declarar como virtual el destructor de la clase base, hace que automáticamente los destructores de las clases derivadas sean también virtuales, a pesar de tener nombres distintos.

Informática II 2011/2 55 C ONSTRUCTORES Y D ESTRUCTORES V IRTUALES Los constructores no pueden ser virtuales, lo que se hace es crear funciones “clones” en la clase base para que simulen la llamada de un constructor derivado. De este modo si es posible declararlo como virtual y redefinirlo en cada clase derivada para que realice una copia exacta del objeto. C ONSTRUCTORES C OPIA V IRTUALES

E JEMPLO C ONSTRUCTORES C OPIA V IRTUALES Ejemplo: El método clonar permite copiar un objeto derivado a través de un puntero de la clase base. Informática II 2011/2 56 vehiculo* carro::clonar(){ //return new carro(*this); vehiculo *ptr=new carro(*this); return ptr; } vehiculo* vehiculo::clonar(){ //return new vehiculo(*this); vehiculo *ptr=new vehiculo(*this); return ptr; } int main(){ vehiculo *ptrV1=new carro(30,true); vehiculo *ptrV2=ptrV1->clonar(); //objeto original cout getVel()<<endl; //objeto clonado cout getVel()<<endl; } 30

Informática II 2011/2 57

Bibliografía Aprenda C++ Avanzado como si estuviera en primero. Tecnun. C con clase o o Sams Teach yourselft C++ in 21 days Informática II 2011/2