Sei sulla pagina 1di 78

LENGUAJE DE PROGRAMACION III C++ PROGRAMACIN ORIENTADA A OBJETOS Docente: Ing.

ALVARO ADRIAN IZQUIERDO GOMEZ TEMAS: UNIDAD 1. PROGRAMACION ORIENTADA A OBJETOS EN C++ 1. Introduccin a las clases 2. Clases 3. Arrays, punteros y referencias 4. Sobrecarga de funciones 5. Sobrecarga de operadores 6. Herencia 7. Sistema de E/S 8. Funciones virtuales 9. Plantillas y manejo de excepciones 10. Juegos en C++ utilizando libreras SDL 1. 2. 3. 4. 5. 6. 7. 8. 9. UNIDAD 2. PROGRAMACION ORIENTADA A OBJETOS EN JAVA Introduccion Caractersticas generales de JAVA Diferencias entre C++ y JAVA Las Clases en JAVA Herencia y Polimorfismo Programacion orientada a Eventos Hilos Applets Interfaces grficas

Guias de Estudio Lenguaje Orientado a Objetos, desarrolladas por: Adrin Izquierdo, docente ITP

ACTA DE ENCUADRE PEDAGGICO MATERIA LENGUAJE ORIENTADO A OBJETOS CURSO: SISTEMAS III DOCENTE: ALVARO ADRIAN IZQUIERDO Sibundoy, Lunes 9 de Agosto de 2010 Siendo las 8:00 pm del 10/02/2010 se reunieron en el Instituto Tecnolgico, los estudiantes de la materia LENGUAJE ORIENTADO A OBJETOS el docente a cargo de ella ALVARO ADRIAN IZQUIERDO GMEZ y acordaron los siguientes puntos para un ptimo desarrollo de la asignatura: El docente se compromete a: 1. ser puntual tanto en la hora de llegada como en la de salida 2. dar a conocer la temtica y la metodologa 3. cumplir con el plan de trabajo al 100% a menos que existan inconvenientes externos como Paros, y otros eventos no programados que entorpezcan la labor acadmica 4. explicar con clase magistral, guias, talleres y prcticas los diferentes temas 5. evaluar de manera justa el trabajo de los estudiantes 6. a tratar a todos los estudiantes por igual Los estudiantes se compromenten a: 1. asistir a clases y ser puntuales tanto en la hora de llegada como en la hora de salida 2. estar atentos en clase y realizar la actividades que se generen dentro y fuera de ella 3. leer las guas, realizar talleres, presentar los parciales y prcticas con responsabilidad 4. tratar con respeto a sus compaeros y al docente 5. compromiso con la asignatura y con ellos mismos para cumplir con los objetivos prouestos 6. a tener en cuenta los siguiente criterios de evaluacin CRITERIOS DE EVALUACIN Investigaciones, Trabajos, Ejercicios, Parciales
Porcentaje 30 Actividades Ejercicios desarrollados Practica 1 Parcial Ejercicios desarrollados Practica 2 Parcial Ejercicios desarrollados Practica final Examen Final TOTAL Valor % 5 10 15 5 10 15 5 15 20 100

30

40

FIRMAS ____________________________________________ ____________________________________________ ____________________________________________ ____________________________________________ ____________________________________________ ____________________________________________ ____________________________________________ ____________________________________________ ____________________________________________ ____________________________________________ ____________________________________________

DOCENTE ESTUDIANTE ESTUDIANTE ESTUDIANTE ESTUDIANTE ESTUDIANTE ESTUDIANTE ESTUDIANTE ESTUDIANTE ESTUDIANTE ESTUDIANTE

Guias de Estudio Lenguaje Orientado a Objetos, desarrolladas por: Adrin Izquierdo, docente ITP

____________________________________________ ____________________________________________

ESTUDIANTE ESTUDIANTE

Guias de Estudio Lenguaje Orientado a Objetos, desarrolladas por: Adrin Izquierdo, docente ITP

Bibliografa: Guas de clase del docente Alvaro Adrin Izquierdo El Lenguaje de Programacin C++, Stroustrup Ingeniera del Software, Sommerville Programacin en Java una introduccion a la Programacion Orientada a Objetos, C. Thomas Wa C++ cmo programar, Deitel Algoritmos, estructuras de datos y Programacion Orientada a Objetos, Roberto Florez Rueda Visual BASIC.NET, Francisco Javier Ceballos Programming with C++, Shaum's Ingeniera de Software Orientado a Objetos, Bruegge Dutoit Java cmo programar, Deitel C++ Gua de Autoenseanza, Herbert Schildt Programacin y Diseo en C++, James P. Cohoon Jack W. Davidson, Una herramienta para la Programacin Orientada a Objetos, Csar Becerra Santamara The C++ Programming Language, 3 ed.B. Stroustrup Sitios Web: http://www.casarramona.com/mt/programador/ http://www.solocodigo.com/ http://www.mhhe.com/c++programdesign http://www.cs.virginia.edu/cs101

Guias de Estudio Lenguaje Orientado a Objetos, desarrolladas por: Adrin Izquierdo, docente ITP

INTRODUCCIN A LA P.O.O. La programacin orientada a objetos es una nueva manera de enfocar la programacin. Ateriormente existi Programas mediante un proceso de cambio de conmutadores. Lenguaje ensamblador Apareci el FORTRAN como primer lenguaje de alto nivel (aos 50) Lenguajes de programacin estructurados (aos 70) Algol, C y Pascal Programacin orientada a objetos. Caractersticas: o Encapsulacin o Polimorfismo o Herencia Encapsulacin: Mecanismo que agrupa al cdigo y los datos que maneja y los mantiene protegidos frente a cualquier interferencia y mal uso. Un objeto es el dispositivo que soporta encapsulacin. Polimorfismo: En donde un nombre se utiliza para dos o ms propsitos relacionados pero tcnicamente diferentes. Ejemplo como en C se necesitan tres funciones para calcular el valor absoluto: abs(), labs() y fabs(). En C++ es posible construir una sola funcin que soporte para diferentes tipos de datos abs(). El tipo de datos utilizado para llamar a la funcin determina qu versin especfica de la funcin se est usando. Adems de las funciones, se puede utilizar polimorfismo tambin a los operadores. Herencia: Proceso mediante el cual un objeto puede adquirir las propiedades de otro. Un objeto puede heredar un conjunto general de propiedades a las que puede aadir aquellas que son especficamente suyas. La importancia de la herencia radica en el hecho de permitir que un objeto soporte el concepto de clasificacin jerrquica. E/S por consola de C++: cout: Es el flujo predefinido que enlaza con la consola. Utilizando el operador de salida << es posible sacar cualquier tipo bsico de C++ Sintaxis: cout << expresin; Ejemplos: cout << Mensaje por pantalla.\n; cout << 234.22; cin: Flujo predefinido que enlaza al teclado. Se utiliza el operador de entrada >>. Sintaxis: cin >> expresin; Ejemplo: int numero; cin >> numero; Ejemplos: 1. Programa que muestra una cadena, dos valores enteros y un valor real doble: #include <iostream.h> main() Guias de Estudio Lenguaje Orientado a Objetos, desarrolladas por: Adrin Izquierdo, docente ITP

{ int i,j; double d; i=10; j=20; d=99.101; cout << algunos valores:; cout << i; cout << ; cout <<j; cout << ; cout <<d; //Mostrar ms de un valor en una sola expresin de E/S cout << Algunos valores:; cout << i << << j << << d; return 0; } 2. Este programa pide al usuario un valor entero: #include <iostream.h> main() { int i; cout << Introduzca un valor: ; cin >> i; cout << El nmero es: << i << \n; return 0; } 3. El siguiente programa pide al usuario un valor entero, un real y una cadena. #include <iostream.h> main() { int i; float f; char s[80]; cout << Introduzca un entero, un real y una cadena:; cin >> i >> f >> s; cout << Estos son sus datos: ; cout << i << << f << << s; return 0; }

Guias de Estudio Lenguaje Orientado a Objetos, desarrolladas por: Adrin Izquierdo, docente ITP

1. INTRODUCCIN A LAS CLASES Clase: Una de las caractersticas ms importante de C++. Es el mecanismo para crear objetos. La sintaxis de una declaracin de clase es similar a la de una estructura Class nombre-clase { Funciones y variables privadas de la clase public: Funciones y variables pblicas de la clase } lista de objetos; Las funciones y variables declaradas dentro de una declaracin de clase se dice que son miembros de esa clase. Por omisin, todas las funciones y variables declaradas en una clase son privadas para esa clase. Para declarar miembros de clase pblicos se utiliza la palabra clave public: Ej: class miclase { int a; public: void poner_a (int num); void traer_a (); }; Dado que a es privada, no es accesible por ningn otro cdigo que est por fuera de miclase. Sin embargo, dado que poner_a() y traer_a() son miembros de miclase, pueden acceder a a. Ejemplo: #include <iostream.h> class miclase { int a; public: void poner_a (int num); void traer_a (); }; void miclase::poner_a(int num) { a = num; } int miclase::traer_a() { return a; } main() Guias de Estudio Lenguaje Orientado a Objetos, desarrolladas por: Adrin Izquierdo, docente ITP

{ miclase objeto1, objeto2; objeto1.poner_a (10); objeto2.poner_a (20); cout << objeto1.traer_a() << \n; cout << objeto2.traer_a() << \n; return 0; } Igual que puede haber funciones miembro pblicas, tambin puede haber variables miembro pblicas. Ej: si a se hubiera declarado en la seccin pblica de miclase, entonces cualquier parte del programa podra referenciar a a, como se muestra a continuacin: #include <iostream.h> class miclase { public: int a; //ahora a es publica };

no haria falta poner_a() ni traer_a()

main(){ miclase ob1, ob2; //se accede de manera directa a la variable de clase a ya que es publica ob1.a = 34; ob2.a = 56; cout << ob1.a << \n; cout << ob2.a << \n; return 0; }

Guias de Estudio Lenguaje Orientado a Objetos, desarrolladas por: Adrin Izquierdo, docente ITP

Ejemplo: Programacin de una pila usando objetos: #include <iostream.h> #define MAX 10 //declara una clase pila de caracteres class pila{ char p[MAX]; //guarda los caracteres que se van apilando int t; public: void iniciar(); //inicializa la pila void meter(char ch); //mete carcter en la pila char sacar(); //saca carcter de la pila }; //inicializa la pila void pila::iniciar() { t=0; } //Mete un carcter en la pila void pila::meter(char ch) { if(t==MAX){ cout <<La pila esta llena; return; } p[t]=ch; t++; } //Saca un carcter char pila::sacar() { if(t==0){ cout << La pila esta vacia \n; return o; } t--; return p[t]; } //programa principal que hace uso de la clase pila creando dos objetos pila

Guias de Estudio Lenguaje Orientado a Objetos, desarrolladas por: Adrin Izquierdo, docente ITP

main(){ pila op1, op2; //crea dos pilas int i; //inicializa las pilas op1.iniciar(); op2.iniciar(); //meter caracteres en las pilas op1.meter('a'); op1.meter('b'); op1.meter('c'); op1.meter('d'); op2.meter('x'); op2.meter('y'); op2.meter('z'); for(i=0; i<4; i++) cout << Saca de op1: << op1.sacar() <<\n; for(i=0; i<3; i++) cout << Saca de op2: << op2.sacar() <<\n; return 0; } Actividad: Investigar las palabras claves en C++ Funciones constructoras y destructoras Es necesario en la mayora de programas que las variables de clase (son las varibles que pertenecen a una clase y se ubican tanto en las secciones public, private y protected) sean inicializadas. Para esto se crearon las funciones constructoras, que se distinguen por llevar el mismo nombre de la clase. Ej: #include <iostream.h> class miclase{ int a; public: miclase(); //es la constructora void mostrar(); }; //implementacion de la funcion constructora, observar que no tiene tipo devuelto miclase::miclase(){ cout << En construccion\n; a=10; } //implementacion de la funcion mostrar void miclase::mostrar(){ cout <<a; Guias de Estudio Lenguaje Orientado a Objetos, desarrolladas por: Adrin Izquierdo, docente ITP

} //utilizacion desde el main main() { miclase ob; //se inicializa el objeto llamando al constructor ob.mostrar(); return 0; } Los constructores como se vio en el ejemplo, no tienen tipo devuelto, es decir no retornarn nada y tampoco se le debe poner void. El complemento de un constructor es el destructor. A esta funcin se le llama cuando se destruye el objeto. Cuando se trabaja con objetos es muy comn tener que realizar algunas acciones cuando se destruye el objeto. Por ejemplo, un objeto que asigna memoria cuando se crea, querr liberar la memoria cuando se destruya. El nombre de un destructor es el nombre de la clase a la que pertenece precedido del carcter ~ . Veamos el ejemplo modificado #include <iostream.h> class miclase{ int a; public: miclase(); //es la constructora ~miclase(); //es la destructora void mostrar(); }; //implementacion de la funcion constructora, observar que no tiene tipo devuelto miclase::miclase(){ cout << En construccion\n; a=10; } //implementacion de la funcion constructora, observar que no tiene tipo devuelto miclase::~miclase(){ cout << Destruyendo\n; } //implementacion de la funcion mostrar void miclase::mostrar(){ cout <<a; } //utilizacion desde el main main() { Guias de Estudio Lenguaje Orientado a Objetos, desarrolladas por: Adrin Izquierdo, docente ITP

miclase ob; //se inicializa el objeto llamando al constructor ob.mostrar(); return 0; } Al destructor de la clase se le llama cuando se destruye un objeto. Los objetos locales se destruyen cuando se salen del mbito. Los objetos globales se destruyen cuando se finaliza el programa. No es posible obtener la direccion de un constructor ni de un destructor. Ejemplo: Recordemos la clase pila donde se necesitaba de una funcion iniciar, ahora vamos a inicializar mediante un constructor. #include <iostream.h> #define MAX 10 //declara una clase pila de caracteres class pila{ char p[MAX]; //guarda los caracteres que se van apilando int t; public: pila(); // constructor para inicializar la pila ~pila(); //destructor de la pila void meter(char ch); //mete carcter en la pila char sacar(); //saca carcter de la pila }; //inicializa la pila pila::pila() { cout <<Construyendo la pila\n; t=0; } //destructor de la pila pila::~pila() { cout <<destruyendo la pila\n; } //Mete un carcter en la pila void pila::meter(char ch) { if(t==MAX){ cout <<La pila esta llena; return; } p[t]=ch; t++; } Guias de Estudio Lenguaje Orientado a Objetos, desarrolladas por: Adrin Izquierdo, docente ITP

//Saca un carcter char pila::sacar() { if(t==0){ cout << La pila esta vacia \n; return o; } t--; return p[t]; } //programa principal que hace uso de la clase pila creando dos objetos pila main(){ pila op1, op2; //crea dos pilas que se inicializan automaticamente por el construc int i; //meter caracteres en las pilas op1.meter('a'); op1.meter('b'); op1.meter('c'); op1.meter('d'); op2.meter('x'); op2.meter('y'); op2.meter('z'); for(i=0; i<4; i++) cout << Saca de op1: << op1.sacar() <<\n; for(i=0; i<3; i++) cout << Saca de op2: << op2.sacar() <<\n; return 0; } Constructores con parmetros Es posible pasar argumentos a una funcin constructora. Para permitir esto, simplemente se aade los parmetros adecuados a la declaracin y definicin de la funcin constructora. Despus, cuando se declara el objeto, se especifica los parmetros como argumentos. Ejemplo: #include <iostream.h> class miclase{ int a; public: miclase(int x); //constructor con parametro void mostrar(); }; miclase::miclase(int x) Guias de Estudio Lenguaje Orientado a Objetos, desarrolladas por: Adrin Izquierdo, docente ITP

{ cout <<En el constructor\n; a=x; //se asigna a la variable de clase a el valor de la variable x } void miclase::mostrar() { cout <<a<<\n; } main(){ miclase ob(4); ob.mostrar(); return 0; } Introduccion a la herencia La herencia es un mecanismo por el cual una clase puede heredar las propiedades de otra. La herencia permite jerarqua de clases, partiendo de la ms general a la ms especfica. Cuando una clase hereda otra, la clase que se hereda se llama clase base. La clase que hereda se llama clase derivada. Clase base Figura Geometrica area Rectangulo ancho, alto

Clase derivada

En la figura se puede observar que existe una clase base que se llama Figura Geomtrica y que tiene una propiedad (o variable de clase) llamada area ya que toda figura geomtrica tiene un area. Luego se observa que existe una clase derivada llamada Rectangulo, la cual tiene dos propiedades: ancho y alto; adems ntose que esta clase hereda la propiedad area de la clase base. El cdigo para estas clases podra ser algo como esto: class figura_geometrica{ public: float area .... }; class rectangulo : public figura_geometrica{ float ancho, alto; .... } Tras el nombre de la clase rectngulo hay dos puntos seguidos por la palabra clave public y el nombre de la clase figura_geometrica. Esto le dice al compilador que la clase rectangulo heredar todos los componentes de la clase figura_geometrica. La palabra clave pblic le indica al Guias de Estudio Lenguaje Orientado a Objetos, desarrolladas por: Adrin Izquierdo, docente ITP

compilador que figura_geometrica se heredar, as como que todos los elementos pblico de la clase base sern elementos pblicos derivada. Sin embargo, todos los elementos privados de la clase base premanecen privados para ella y no son accesibles directamente por la clase derivada. En el ejemplo, en la clase rectangulo se podra perfectamente hacer referencia a la variable area ya que se hereda por ser publica en la clase base. Ejemplo: #include <iostream.h> //define la clase base class base{ int i; public: void poner_i(int n); int traer_i(); }; //define la clase derivada class derivada : public base{ int j; public: void poner_j(int n); int mul(); }; //establecer el valor de i en la clase base void base::poner_i(int n) { i=n; } //devuelve el valor de i de la clase base int base::traer_i() { return i; } //Establece el valor de j en la clase derivada void derivada::poner_j(int n) { j=n; } //devuelve el valor de i de la base por el valor de j de la derivada int derivada::mul() { return j * traer_i(); //se puede acceder a la funcion y no directa/ a i }

Guias de Estudio Lenguaje Orientado a Objetos, desarrolladas por: Adrin Izquierdo, docente ITP

main(){ derivada ob; ob.poner_i(10); //carga i en la base. No se podra decri ob.i=10 porque i no se hereda ob.poner_j(5); //carga i en la derivada cout <<ob.mul(); //muestra 50 return 0; } Actividad: 1. Dada la siguiente clase base: class area_c1{ public: double ancho; double alto; }; Cree dos clases derivadas llamadas cuadro e isosceles que hereden area_c1. Haga que cada clase incluya una funcin llamada area() que devuelva el rea de un cuadrado o un tringulo isoceles, respectivamente. Use constructores con parmetros para inicializar ancho y alto.

Guias de Estudio Lenguaje Orientado a Objetos, desarrolladas por: Adrin Izquierdo, docente ITP

Herencia: Cuando una clase hereda otra, la clase que se hereda se llama clase base, la clase que hereda se llama clase derivada. Ej: class B{ int i; public: void set_i(int n); int get_i(); }; class D : public B{ int j; public: void set_j(int n); int mul(); }; Punteros a Objetos: Hasta ahora se ha accedido a los miembros de los objetos por medio de la notacin punto. Es posible hacerlo tambin con la notacin flecha () . Un puntero a objeto se declara igual que se declara un puntero a cualquier otro tipo de variable. Se especifica su nombre de clase y luego se precede el nombre de la variable con un asterisco (*). Para obtener la direccin de un objeto, se precede al objeto con el operador &. #include <iostream.h> class miclase{ int a; public: miclase(int x);//constructor int get(); }; miclase::miclase(int x){ a=x; } int miclase::get(){ return a; } main(){ miclase ob1(20);//crea un objeto miclase ob2(30);//crea otro objeto miclase *p; //apuntador de tipo miclase p=&ob1; //pone la direccion de ob1 en p cout <<Valor utilizando el objeto1 : << ob1.get() <<\n; Guias de Estudio Lenguaje Orientado a Objetos, desarrolladas por: Adrin Izquierdo, docente ITP

cout <<Valor utilizando el apuntador : << p->get <<\n; return 0; } Funciones Insertadas: En C++, es posible definir funciones a las que no se llaman realmente, pero se inserta en el cdigo en el momento de cada llamada. Es similar a las macro instrucciones con parmetros del C. La ventaja que tienen las funciones insertadas es que no tienen nada asociado con el mecanismo de llamada y vuelta de la funcin. Esto hace que estas funciones se ejecuten ms rapidamente que las funciones normales. La desventaja es que en las funciones insertadas si son muy largras y se les llama frecuentemente, el programa aumentar su longitud. Por esta razn solo unas pocas funciones se declaran como insertadas. Para declarar una funcin como insertada hay que preceder la definicin de la funcin con la palabra clave inline. //Ejemplo de funcin insertada #include <iostream.h> inline int par(int x) { return !(x%2); } main(){ if par(12)) cout << 12 es par\n; if par(15)) cout << 15 es par\n; return 0; } Aqu la instruccin: if par(12)) cout << 12 es par\n; se convierte en if !(12%2)) cout << 12 es par\n; Una funcin insertada tiene que definirse antes de ser llamada. Adems tiene que ser sencilla, de lo contrario dependiendo del compilador, este la puede tratar como una funcin normal. Cualquier tipo de funcin se puede insertar incluso las funciones que son miembros de una clase: #include <iostream.h> class ejemplo{ int i,j; public: ejemplo(int a, int b); int divisible(); }; ejemplo:ejemplo(int a, int b){ i=a; Guias de Estudio Lenguaje Orientado a Objetos, desarrolladas por: Adrin Izquierdo, docente ITP

j=b; } inline int ejemplo::divisible(){ return !(i%j); } main(){ ejemplo ob1(10,2), ob2(10,3); //esto es verdadero if (ob1.divisible()) cout << 10 es divisible por 2\n; //esto es falso if (ob2.divisible()) cout << 10 es divisible por 3\n; return 0; } Insercin automtica Si la definicin de una funcin miembro es corta, se puede incluir dentro de una declaracin de clase. Esto provoca que la funcin se convierta automticamente en insertada, en esta caso no se necesita la palabra clave inline, aunque no es un error escribirla. #include <iostream.h> class ejemplo{ int i, j; public: ejemplo(int a, int b); //aqui la funcion insertada automticamente int divisible() { return !(i%j); } }; Contina igual que el ejemplo anterior Ejercicios pag 57,58,59, 62 Asignacin de Objetos Un objeto se puede asignar a otro siempre que ambos objetos sean del mismo tipo. Por omisin se hace una copia a nivel de bits de todos los miembros. #include <iostream.h> class miclase{ int a, b; public: void set (int i, int j) { a=i; b=j;} void show() {cout << a << ' ' << b << \n;} Guias de Estudio Lenguaje Orientado a Objetos, desarrolladas por: Adrin Izquierdo, docente ITP

}; main(){ miclase o1, o2; o1.set(20,5); //se asigna o1 a o2 o1.show(); //Escribe 20 5 o2.show(); //Escribe 20 5 return 0; } Los objetos que tienen lugar en una asignacin est separados y son independientes el uno del otro, por lo tanto culquier cambio que se realice en las variables de clase del uno no afectan al otro. Paso de objetos a funciones Por defecto todos los objetos se pasan por valor a una funcin, es decir se hace una copia idntica del argumento y esta copia es usada por la funcin. #include <iostream.h> class ejemplo { int i; public: ejemplo (int n) {i=n;} int get_i() {return i;} }; //Devuelve el cuadrado de i int cuadrado (ejemplo o){ return o.get_i() * o.get_i(); } main (){ ejemplo a(5), b(2); cout << cuadrado(a) << \n; //Escribe 25 cout << cuadrado(b) << \n; //Escrib 4 return 0; } Los objetos tambin pueden ser pasados por referencia, para que se modifiquen en la funcin, en este caso se envi la direccin del objeto. #include <iostream.h> class ejemplo { int i; public: ejemplo (int n) {i=n;} void set_i(int n) {i=n;} Guias de Estudio Lenguaje Orientado a Objetos, desarrolladas por: Adrin Izquierdo, docente ITP

int get_i() {return i;} }; //Funcion que recibe un apuntador a objeto int cuadrado (ejemplo *o){ o->set_i(o->get_i() * o->get_i()); } main (){ ejemplo a(5); cuadrado (&a); //Se envia la direccion del objeto a cout << a.get_i(); //Escribe 25 return 0; } Cuando se crea una copia de un objeto porque se usa como argumento para una funcin, no se llama a la funcin constructora. Pero cuando la copia se destruye (al terminarse la funcin), se llama a la funcin destructora #include <iostream.h> class ejemplo{ int i; public: ejemplo(int n){ i= n; cout << Construyendo\n;} ~ejemplo() {cout <<Destruyendo\n;} int get_i() {return i;} }; // int cuadrado(ejemplo o){ return o.get_i() * o.get_i(); } main(){ ejemplo a(10); cout << cuadrado(a) << \n; return 0; } Esta funcin mostrar lo siguiente: Construyendo Destruyendo 100 Destruyendo El primer Destruyendo se origina cuando se sale de la funcin y se destruye el objeto o y el segundo Destruyendo se da lugar cuando se destruye el objeto a (al terminar el main).

Guias de Estudio Lenguaje Orientado a Objetos, desarrolladas por: Adrin Izquierdo, docente ITP

Objetos devueltos por funciones Para que una funcin devuelva un objeto, primero hay que especificar de que tipo es el objeto que la funcin devolver, por ejemplo: miclase f(), en este caso se declara la funcin f para que devuelva un objeto de tipo miclase; luego dentro de la funcin hay que devolver el objeto con return. Hay que tener en cuenta que cuando una funcin devuelve un objeto, se crea automticamente un objeto temporal que guarda el valor devuelto; despue de devolver el valor, el objeto se destruye. Esto puede ocasionar efectos inesperados. Ej: #include <iostream.h> #include <string.h> //libreria para poder trabajar con cadenas, en este caso la funcion strcpy class ejemplo { char s[80]; public: void show(){cout << s << \n;} void set(char *cad) { strcpy (s, cad); } //copia la cadena cad en s }; //devuelve un objeto de tipo ejemplo ejemplo entrada(){ //se declara la funcion entrada de tipo ejemplo char x [80]; // cadena de caracteres de longitud 80 ejemplo obj1; //se crea un objeto de tipo ejemplo cout << Introduzca una cadena: ; //mensaje en patalla cin >> x; //lee la cadena y la guarda en x obj1.set(x); //pone la cadena x en el objeto return obj1; //retorna el objeto } main(){ ejemplo ob; ob = entrada(); //asigna el objeto devuelto a ob ob.show(); // muestra el valor de la cadena s que tiene asiganado este objeto return 0; } Es necesario tener cuidado cuando se devuelven objetos, si estos contienen funciones destructoras, ya que como se dijo anteriormente, cuando se devuelve un objeto, se crea uno temporal que despus es destruido automticamente. Veamos otra versin del programa anterior: //Error generado al devolver un objeto #include <iostream.h> #include <string.h> #include <stdlib.h>

Guias de Estudio Lenguaje Orientado a Objetos, desarrolladas por: Adrin Izquierdo, docente ITP

class ejemplo{ char *s; public: ejemplo() { s= '\0';} //se inicia la cadena s con fin de arreglo ~ejemplo() {if (s) free(s); cout << Liberando s\n;} //libera la cadena si no es vacia void show() {cout << s << \n;} //muestra lo que hay en la cadena s void set(char *str); }; //implementar la funcin set void ejemplo::set(char *str){ s = (char *) malloc (strlen(str)); //pide a la memoria la cantidad de bytes necesarios para el //tamao de la cadena if(!s) { //si la cadena s es nula cout << Error de asignacin\n; exit(1); //sale con error } //si las cosas van bien, es decir si se reserv memoria para la cadena s strcpy(s, str); //copia la cadena str en la cadena s } //funcion que devuelve un objeto de tipo ejemplo ejemplo entrada(){ char x[80]; ejemplo e; cout << Ingrese una cadena\n: ; cin >> x; e.set(x); return e; } main(){ ejemplo ob; //asigna el objeto devuelto a ob ob = input(); //Aqui se genera el error ob.show(); return 0; } Al correr este programa se generara esto Ingrese una cadena : Instituto Liberando s Liberando s Instituto Liberando s Guias de Estudio Lenguaje Orientado a Objetos, desarrolladas por: Adrin Izquierdo, docente ITP

Asignacion de puntero nulo Ntese que se llama tres veces a la funcin destructora. Primero cuando el objeto local e sale del mbito al volver de entrada(). La segunda vez es cuando se llama al destructor ~ejemplo cuando se destruye el objeto temporal devuelto por por entrada(). La tercera vez es cuando se termina el main al destruir ob. El mensaje de Asignacin de un puntero nulo se da porque al llamar al destructor la primera vez se libera la memoria asignada para guardar la cadena de entrada por la funcina entrada(). As no solo las otras dos llamadas al destructor de ejemplo intentan liberar una parte de memoria dinmica ya liberada, sino que destruyen el sistema de asignacin dinmica en el proceso. Por esto hay que tener cuidado cuando en las funciones destructoras se libera memoria, porque podramos destruir a los objetos originales que queremos trabajar. Introduccin a las funciones amigas En algunas situaciones es necesario que una funcin tenga acceso a los miembros privados de una clase sin que esta funcin sea un miembro de esa clase. Para esto estn las funciones amigas. Una funcin amiga no es miembro de una clase, pero tiene acceso a los elementos privados la clase. Las funciones amigas se usan comnmente para la sobrecarga de operadores y la creacin de funciones de E/S. Veamos una breve introduccin a las funciones amigas mediante un ejemplo: #include <iostream.h> class miclase{ int n, d; //miembros privados public: miclase(int i, int j) { n=i; d=j;} friend int esfactor (miclase ob); //se declara esfactor como funcion amiga //esta funcion tendra acceso a las variables privadas n y d //no es una funcin miembro de miclase, es amiga nada ms //por tanto no se implementa dentro de la miclase }; //aqui declaramos la funcion esfactor, recordemos que es amiga de miclase //por lo tanto aqu podemos acceder a los miembros privados de miclase como n y d int esfactor(miclase ob){ if(!(ob.n % ob.d) //se accede a n que es un miembro privado de ob return 1; else return 0; } main(){ miclase ob1(10,2), ob2(13,3); if (esfactor(ob1)) cout <<2 es factor de 10\n; else cout << 2 no es factor de 10\n;

Guias de Estudio Lenguaje Orientado a Objetos, desarrolladas por: Adrin Izquierdo, docente ITP

if (esfactor(ob2)) cout <<3 es factor de 13\n; else cout << 3 no es factor de 13\n; return 0; } Hay que tener en cuenta que una funcin amiga no es miembro de la clase que es amiga, por lo tanto la siguiente instruccin dentro del main sera erronea: ob1.esfactor() ya que ob1 no tiene una funcion miembro dentro de su clase llamada esfactor, esta funcin es slo amiga.

Guias de Estudio Lenguaje Orientado a Objetos, desarrolladas por: Adrin Izquierdo, docente ITP

Arrays, punteros y referencias Arrays de Objetos Como cualquier variable, los objetos tambin pueden agruparse en arreglos y su declaracin y acceso se realiza igual como si fuera una variable comn. Ej: #include <iostream.h> class ejemplo { int a; public: void dar_a(int n) {a=n;} int traer_a() {return a;} }; main() { ejemplo ob[4]; int i; //ciclo para dar a cada objeto del arreglo un valor i for (i=0; i<4;i++) ob[i].dar_a(i); //ciclo para imprimir la variable a de cada objeto del arreglo for (i=0; i<4;i++) cout << ob[i].traer_a(i); cout << \n; return 0; } Grficamente el ejemplo anterior cre un arreglo de objetos as: a dar traer ob[0] a dar traer ob[1] a dar traer ob[2] a dar traer ob[3]

Despus de recorrer el primer ciclo quedara el arreglo de la siguiente manera: a 0 dar traer ob[0] a 1 dar traer ob[1] a 2 dar traer ob[2] a 3 dar traer ob[3]

Guias de Estudio Lenguaje Orientado a Objetos, desarrolladas por: Adrin Izquierdo, docente ITP

El segundo ciclo lo que hace es mostrar por pantalla los valores de a cada uno de los objetos del arreglo, entonces se mostrar: 0 1 2 3 Si un tipo de clase incluye un constructor, puede inicializarse un array de objetos Ej: //incializacin de un array #include <iostream.h> class ejemplo{ int a; public: ejemplo(int n){ a=n; } //constructor con un solo argumento int traer_a() { return a; } }; main() { //se inicializa cada objeto con un valor que va al constructor ejemplo ob[4] = { -1, -2, -3, -4 }; int i; //muestra el valor de la variable a de cada objeto for (i=0; i<4; i++) cout << ob[i].traer_a() << ; cout << \n; return 0; } Grficamente, en la primera instruccin del programa anterior se realiza el siguiente proceso:

a -1 traer ob[0]

a -2 traer ob[1]

a -3 traer ob[2]

a -4 traer ob[3]

El ciclo hace que se muestre en pantalla el valor de la variable de clase a de cada objeto, en este caso reportara: -1 -2 -3 -4 El programa anterior hubiera podido haberse escrito modificando la primera instruccin del main: ejemplo ob[4] = { -1, -2, -3, -4 }; por ejemplo ob[4] = { ejemplo(-1), ejemplo(-2), ejemplo(-3), ejemplo(-4) }; Guias de Estudio Lenguaje Orientado a Objetos, desarrolladas por: Adrin Izquierdo, docente ITP

Cuando la funcin constructora recibe un solo argumento y se desea crear un array de objetos, es posible usar cualquiera de las instrucciones anteriores; en este caso este cambio no afectara en nada al programa, el empleo de la ultima instruccin de las anteriores sera importante en el caso en que la funcin constructora reciba ms de un argumento. Veamos, si el programa se hubiera construido as: //incializacin de un array #include <iostream.h> class ejemplo{ int a, b; public: ejemplo(int n, int m){ a=n; b=m; } //constructor con ms de un argumento int traer_a() { return a; } int traer_b() { return b; } }; main() { //se inicializa cada objeto con un valor que va al constructor ejemplo ob[4] = { ejemplo(-1, 3), ejemplo(-2, 5), ejemplo(-3, 7), ejemplo(-4, 9) }; int i; //muestra el valor de la variable a de cada objeto for (i=0; i<4; i++) cout << ob[i].traer_a() << ; //muestra el valor de la variable b de cada objeto for (i=0; i<4; i++) cout << ob[i].traer_b() << ; cout << \n; return 0; } Tambin es posible crear arrays de objetos multidimensionales: Ej: //incializacin de un array bidimensional

#include <iostream.h> class ejemplo{ int a; public: Guias de Estudio Lenguaje Orientado a Objetos, desarrolladas por: Adrin Izquierdo, docente ITP

ejemplo(int n){ a=n; } //constructor un argumento int traer_a() { return a; } }; main() { //se inicializa cada objeto con un valor que va al constructor ejemplo ob[4][2] = { 1, 2, 3, 4, 5, 6, 7, 8 }; int i; //muestra el valor de la variable a de cada objeto for (i=0; i<4; i++) cout << ob[i][0].traer_a() << , ; cout << ob[i][1].traer_a() << , \n; cout << \n; return 0; } Con arrays de objetos multidimensionales, tambin es posible que el constructor tenga ms de un argumento: //incializacin de un array bidimensional #include <iostream.h> class ejemplo{ int a, b; public: ejemplo(int n, int m){ a=n; b=m; } //constructor ms de un argumento int traer_a() { return a; } int traer_b() { return b; } }; main() { //se inicializa cada objeto con un valor que va al constructor ejemplo ob[4][2] = { ejemplo (1, 2), ejemplo (3,4), ejemplo (5, 6), ejemplo (7,8), ejemplo (9, 10), ejemplo (11,12), Guias de Estudio Lenguaje Orientado a Objetos, desarrolladas por: Adrin Izquierdo, docente ITP

ejemplo (13, 14), ejemplo (15,16) }; int i; //muestra el valor de la variable a de cada objeto for (i=0; i<4; i++) cout << ob[i][0].traer_a() << , ; cout << ob[i][1].traer_a() << , \n; cout << \n; return 0; } El programa anterior nos debe mostrar: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16

Guias de Estudio Lenguaje Orientado a Objetos, desarrolladas por: Adrin Izquierdo, docente ITP

Uso de punteros a objetos en arreglos Es posible acceder a los objetos de un arreglo mediante apuntadores. Para referirse a las variables y funciones miembro de un objeto mediante un apuntador, es necesario utilizar la notacin flecha (). Aritmtica de punteros: Cuando se incrementa en uno el puntero a un objeto de un arreglo, apunta al prximo objeto del arreglo. Cuando se decrementa en uno el puntero a un objeto, este apunta al objeto anterior. Ej: #include <stdio.h> class ejemplo{ int a, b; public: ejemplo (int n, int m){a=n; b=m;} int traer_a(){return a;} int traer_b(){return b;} }; main(){ ejemplo ob[4] = { ejemplo(1,2), ejemplo(3,4), ejemplo(5,6), ejemplo(7,8) }; int i; ejemplo *p; //apuntador tipo ejemplo p= ob; //p apunta al inicio del arreglo for(i=0; i<4; i++){ cout << p->traer_a() << ' '; cout << p->traer_b() << \n; p++; //avanza el objeto } cout << \n; return 0; } Modifique el programa anterior para comprobar que en objetos sueltos (es decir no agrupados por un arreglos), no funciona la aritmtica de punteros. El puntero this En C++ existe un puntero especial llamado el puntero this. this es un apuntador que se pasa automticamente a cualquier funcin miembro de la clase. Es un puntero al objeto que genera la llamada. Guias de Estudio Lenguaje Orientado a Objetos, desarrolladas por: Adrin Izquierdo, docente ITP

Ej: #include <iostream> using namespace std; class ejemplo{ int a, b; public: ejemplo (int a, int b){this->a=a; this->b=b;} //usamos this en el constructor para diferenciar //las variables lobcales( a y b) de las miembro // que tambin se llaman a y b int traer_a(){return this->a;} //usamos el objeto this para retornar a int traer_b(){return b;} //no usamos el objeto this para retornar b, pero es lo mismo }; main(){ ejemplo ob(20,30); cout << ob.traer_a() << ' '; // Escribe 20 cout << ob.traer_b() << "\n"; //Escribe 30 return 0; } Observe que el ejemplo anterior hemos utilizado el puntero this en la funcin constructora, esto se hizo para diferenciar las variables locales a y b de las variables miembro a y b, estas ltimas se acompaan del objeto this. Tambin utilizamos el objeto this en la funcin traer_a en la instruccin return this->a; esto es posible debido a que en toda funcin se recibe el objeto que origin la llamada y se hace alusin a ese objeto mediante el apuntador this. Uso de new y delete Cuando vimos estructuras de datos en el semestre anterior utilizbamos el lenguaje C, en este caso slo contbamos con las funciones malloc() y free() para trabajar con memoria dinmica; en C++ es posible utilizar todava esta forma de trabajar, pero ahora el C++ cuenta con las instrucciones new y delete que hacen ms fcil estas tareas. La instruccin new se utiliza para solicitar memoria y delete para liberarla. La sintxis bsica para estas instrucciones es: puntero = new tipo; delete puntero; La utilizacin de new y delete trae ventajas para programar debido a que no es necesario incluir la librera malloc.h, adems no es necesario realizar ningun cast ( como (struct nodo*)), tampoco se necesita la funcin sizeof para calcular el tamao del objeto, ya que esto se realiza automticamente. Adems hay que tener en cuenta que new y delete se pueden sobrecargar para realizar un sistema de asignacin a la medida del programador. Ej: #include <iostream> Guias de Estudio Lenguaje Orientado a Objetos, desarrolladas por: Adrin Izquierdo, docente ITP

using namespace std; main(){ int *p; //declaramos un apuntador de tipo entero p = new int; // se solicita a la memoria una localizacin para un entero // y p queda apuntado a esa localizacin, si la memoria asigna //de lo contario en p queda almacenado el valor NULL if (!p){ //si no se asigna cout << "Error de asignacion\n"; return 1; // sale del programa con error } *p = 450; // asignamos a la localizacin un valor

//Escribimos el valor almacenado en la localizacion cout << "El valor del contenido de p es: " << *p << "\n"; //por ltimo eliminamos la localizacin delete p; return 0; //sale sin errores } Ahora realicemos un ejemplo con objetos. #include <iostream> using namespace std; class ejemplo{ int a, b; public: void poner_ab(int x, int y){ a=x; b=y;} int producto() {return a*b;} }; main(){ ejemplo *p; p = new ejemplo; // se solicita a la memoria una localizacin para un objeto tipo ejemplo // y p queda apuntado a esa localizacin, si la memoria asigna //de lo contario en p queda almacenado el valor NULL if (!p){ //si no se asigna cout << "Error de asignacion\n"; return 1; // sale del programa con error }

Guias de Estudio Lenguaje Orientado a Objetos, desarrolladas por: Adrin Izquierdo, docente ITP

//a travs de p accedemos a la funcin poner_ab del objeto y le enviamos 9 y 8 p->poner_ab(9,8); //Reportamos el valor del producto entre las variables de clase a y b cout << "El producto de a y b es: " << p->producto() << "\n"; //por ltimo eliminamos la localizacin delete p; return 0; //sale sin errores } Ejercicios: 1. Escriba un programa que utilice new para asignar dinmicamente un float, un long y un char. D valores a estas variables dinmicas y mustrelos. Por ltimo, utilizando delete, libere toda la memoria asignada dinmicamente. 2. Cree una clase que contenga el nombre de una persona y su nmero de telfono. Haciendo uso de new, asigne dinmicamente un objeto a esta clase y coloque dentro de los campos correspondientes del objeto su nombre y su nmero de telfono.

Guias de Estudio Lenguaje Orientado a Objetos, desarrolladas por: Adrin Izquierdo, docente ITP

Caractersticas adicionales sobre new y delete: a. Los objetos asignados dinmicamente pueden recibir valores iniciales. b. Pueden crearse arreglos asignados dinmicamente. a. Los objetos asignados dinmicamente pueden recibir valores iniciales: puntero = new tipo (valor_inicial); Ej: #include <iostream> using namespace std; class ejemplo{ int a, b; public: ejemplo (int x, int y){ a=x; b=y;} int producto() {return a*b;} }; main(){ ejemplo *p; p = new ejemplo(8,9) ; // se solicita a la memoria una localizacin para un objeto tipo ejemplo //adems se enva valores iniciales para el constructor // y p queda apuntado a esa localizacin, si la memoria asigna //de lo contario en p queda almacenado el valor NULL if (!p){ //si no se asigna cout << "Error de asignacion\n"; return 1; // sale del programa con error } //si se asigna el programa continua aqui cout << p->producto() << "\n"; //Escribe 72 return 0; } b. Pueden crearse arreglos asignados dinmicamente: Para asignar dinmicamente un arreglo unidimensional debe utilizarse esta forma de new: apuntador = new tipo [tamao]; En este caso apuntador queda apuntando a la primera posicin del arreglo. Por razones tcnicas no es posible inicializar un arreglo que ha sido asignado dinmicamente, por eso los valores tiene que darse despus de crearse. Para eliminar un arreglo asignado dinmicamente, debe utilizarse la siguiente forma de delete: delete [] apuntador; donde apuntador es el puntero que est apuntado al arreglo.

Guias de Estudio Lenguaje Orientado a Objetos, desarrolladas por: Adrin Izquierdo, docente ITP

Esta sintaxis da lugar a que el compilador llame a la funcin destructora para cada elemento del arreglo. La variable apuntador no se libera en mltiples ocasiones, slo se libera una vez. Ej: #include <iostream> using namespace std; class ejemplo{ int a; public: ~ ejemplo (){ cout << "destruyendo objeto .." << "\n";} void poner_a (int x) { a=x;} int traer_a() {return a;} }; main(){ ejemplo *p; int i; p = new ejemplo [5] ; // se solicita a la memoria una localizacin para un arreglo de cinco objetos tipo ejemplo // y p queda apuntado al primer objeto de esa localizacin, si la memoria asigna, //de lo contario en p queda almacenado el valor NULL if (!p){ //si no se asigna cout << "Error de asignacion\n"; return 1; // sale del programa con error } //ciclo para dar valores a cada objeto for (i=0; i<5; i++) p[i].poner_a(i+1); //ciclo para imprimir el valor de a de cada objeto for (i=0; i<5; i++) cout << "valor a del objeto " << i << "es: " << p[i].traer_a() << "\n"; delete [] p; //se destruyen todos los objetos y p obviamente return 0; } Este programa reporta lo siguiente: valor a del objeto 0es: 1 valor a del objeto 1es: 2 valor a del objeto 2es: 3 valor a del objeto 3es: 4 valor a del objeto 4es: 5 destruyendo objeto .. Guias de Estudio Lenguaje Orientado a Objetos, desarrolladas por: Adrin Izquierdo, docente ITP

destruyendo objeto .. destruyendo objeto .. destruyendo objeto .. destruyendo objeto .. Referencias Una referencia es un apuntador implcito que se comporta como cualquier otro nombre para una variable. Existen tres formas de trabajar con referencias: a. Cuando una referencia se pasa a una funcin. b. Cuando una referencia es devuelta por una funcin. c. Cuando se crea una referencia independiente. a. Cuando una referencia se pasa a una funcin: Para entender esto primero veamos un ejemplo donde se usa un apuntador y no una referencia: Ej: #include <iostream.h> void f(int *n); //uso de un parmetro apuntador prototipo main (){ int i=0; f(&i); //se llama a la funcin f y se le enva la direccin de i cout << Este es el valor de i <<i << que pudo ser modificado en f \n; return 0; } void f(int *n) //se recibe i en un apuntador n, es decir podemos modificar i { //a travs de n *n = 80; // podemos modificar i a travs del apuntador n } El ejemplo anterior no es nada ms que el paso de una variable por referencia a una funcin, la cual debe recibirla en un apuntador, por medio del cual se puede acceder a la variable del main. El programa anterior debe escribir en pantalla lo siguiente: Este es el valor de i 80 que pudo ser modificado en f En C++ es posible automatizar completamente este proceso utilizando un parmetro por referencia, modifiquemos el ejemplo anterior para entenderlo. #include <iostream> using namespace std; void f(int &n); //declaracion de una funcion con parametro referencia prototipo main (){ int i=0; f(i); //se llama a la funcin f y no se enva la direccin de i , slo enva i. cout << "Este es el valor de i " << i << " que pudo ser modificado en f" << "\n"; Guias de Estudio Lenguaje Orientado a Objetos, desarrolladas por: Adrin Izquierdo, docente ITP

return 0; } void f(int &n) //se recibe i en una referencia n { n = 80; // podemos modificar i a travs de la referencia n } El programa escribe por pantalla: Este es el valor de i 80 que pudo ser modificado en f La referencia en la funcin (en este caso n) es como si se tratara de la variable a la que hace referencia (en este caso i). Paso de referencias a objetos: Recordemos que cuando se pasa un objeto a una funcin por valor, se hace una copia del objeto. Aunque no se llame a la funcin constructora del parmetro cuando la funcin finaliza si llama a la funcin destructora. A medida que se produzcan nuevas llamadas pueden presentarse problemas en algunas instancias por ejemplo, cuando se libera memoria dinmica. Una solucin es el paso del objeto por referencia (aunque tambin existe la de crear un constructor de copias). Cuando se pasa un objeto por referencia no se hace ninguna copia y por tanto no se llama a la funcin destructora cuando la funcin finaliza. Aunque no se debe olvidar que los cambios en el objeto dentro de la funcin afectan al objeto utilizado como argumento. Nota: Una referencia no es un apuntador, por lo tanto si se pasa un objeto por referencia, el operador de acceso a un atributo utiliza la notacin punto (.) y nunca flecha (). Para realizar los ejemplos primero crearemos uno donde se enven objetos a una funcin por valor: #include <iostream> using namespace std; class ejemplo{ int w; public: ejemplo (int n) { w = n; cout << "Construccion" << w << "\n"; } ~ejemplo () {cout << "Destruccion " << w << "\n";} int traer_w () { return w;} }; void f(ejemplo o){ cout << "Recibido " << o.traer_w() << "\n"; } Guias de Estudio Lenguaje Orientado a Objetos, desarrolladas por: Adrin Izquierdo, docente ITP

main (){ ejemplo e(3); f(e); // se enva el objeto e por valor, por lo tanto se crea una copia return 0; } Este programa reporta: Construccion3 Recibido 3 Destruccion 3 Destruccion 3 Aqu nos damos cuenta que se llama dos veces a la funcin destructora: una cuando se destruye la copia del objeto al terminar f() y otra cuando se termina el programa (donde se destruye automticamente el objeto e). Veamos qu sucede si en lugar de utilizar paso por valor, utilizamos una referencia: #include <iostream> using namespace std; class ejemplo{ int w; public: ejemplo (int n) { w = n; cout << "Construccion" << w << "\n"; } ~ejemplo () {cout << "Destruccion " << w << "\n";} int traer_w () { return w;} }; void f(ejemplo &o){ cout << "Recibido " << o.traer_w() << "\n"; } main (){ ejemplo e(3); f(e); // se enva el objeto e por valor, por lo tanto se crea una copia return 0; } El programa anterior reporta la siguiente informacin: Construccion3 Recibido 3 Destruccion 3 Por tanto se ve cmo se llama una sola vez a la funcin destructora cuando se finaliza el main (y no como en el programa anterior que se llamaba tambin cuando finalizaba la funcin f). Guias de Estudio Lenguaje Orientado a Objetos, desarrolladas por: Adrin Izquierdo, docente ITP

Realizar ejercicio de la pgina 109.

Guias de Estudio Lenguaje Orientado a Objetos, desarrolladas por: Adrin Izquierdo, docente ITP

b. Cuando una referencia es devuelta por una funcin. Como se devuelve cualquier tipo, una funcin tambin puede devolver una referencia. Esto se usa en la sobrecarga de operadores (tema que se estudiar ms adelante) y en otras sentencias de asignacin. Ej: #include <iostream> using namespace std; int &funcion(); // prototipo int x; //variable global main(){ funcion()=78; //es lo mismo que decir x=78 //ya que funcion() devuelve una referencia a x cout << x << "\n"; //Escribe 78 return 0; } int &funcion(){ //funcin que devuelve una referencia a un int ---> int & return x; //devolucin de una referencia a x } El programa anterior escribe: 78 Hay que tener en cuenta el alcance de las variables, aqu se pudo hacer una referencia a x ya cuando se ejecuta la funcin y se llega nuevamente al main, la variable todava existe (debido a que es global), pero hay que tener cuidado de devolver refencias de variables locales a una funcin. Si en el ejemplo anterior reemplazaramos la funcin por: int &funcion(){ int z; return z; //devolucin de una referencia a z, es errono porque //z desaparecer cuando la funcin termine } c. Cuando se crea una referencia independiente. Una referencia independiente es otro nombre que se le da a una variable. Son muy poco utilizadas y algunos creen que tienden a confundir al programado existiendo ms de un nombre para una misma variable. Ej: #include <iostream> using namespace std; main(){ int v; int &ref_v=v; //Se crea la referencia a v que es ref_v , solo se puede crear al declarar la variable Guias de Estudio Lenguaje Orientado a Objetos, desarrolladas por: Adrin Izquierdo, docente ITP

v=50; cout << "valor de v " << v << " valor de ref_v " << ref_v << endl; ref_v = 200; //dar otro valor a v por medio de ref_v cout << "valor de v " << v << " valor de ref_v " << ref_v << endl; } El programa anterior escribe: valor de v 50 valor de ref_v 50 valor de v 200 valor de ref_v 200

Guias de Estudio Lenguaje Orientado a Objetos, desarrolladas por: Adrin Izquierdo, docente ITP

SOBRECARGA DE FUNCIONES La sobrecarga de funciones es un concepto muy importante en la programacin orientada a objetos debido a que proporciona flexibilidad por el hecho que se pueden crear funciones diferentes pero que presentan mucha semejanza y se les asignan el mismo nombre, aunque hagan algo distinto. En la sobrecarga de funciones, estas pueden tener el mismo nombre pero deben tener diferencias en su lista de parmetros, sea en el nmero de parmetros o sea en variaciones en el tipo de stos. En el siguiente ejemplo se sobrecarga la funcin mediante la variacin en el nmero de parmetros: void f(int a) {} void f(int a, int b) {} void f(int a, int b, int c) {...} // con 1 parmetro //con 2 parmetros //con 3 parmetros

Cuando se llame a la funcin f, se tendr en cuenta cuantos parmetros tiene para determinar cul de las tres es la que se tiene que llamar, si se llama de la siguiente manera: f(4, 9); Se llamara a la funcin f con 2 parmetros. El siguiente ejemplo muestra cmo se sobrecarga una funcin variando los tipos de datos de los parmetros: void f(int a) {} void f(float a) {} // con 1 parmetro int //con 1 parmetro float

Cuando se llame a la funcin f, se tendr en cuenta el tipo de parmetro para determinar cul de las dos es la que se tiene que llamar, si se llama de la siguiente manera: f(250.33); Se llamara a la segunda funcin, la del parmetro float. Sobrecarga de la funcin constructora La sobrecarga de una funcin constructora se utiliza por tres motivos: para ganar flexibilidad, permitir arreglos y para trabajar con constructores de copias. Veamos un ejemplo en donde se sobrecargar un constructor de acuerdo al nmero de parmetros para inicializar un constructor de dos maneras diferentes: Ej: En este caso crearemos una clase rectngulo que tendr un ancho y largo, pero como el cuadrado es un caso especial del un rectngulo debido a que su ancho es igual a su largo, se modificar en constructor para este caso, veamos: #include <iostream> using namespace std; class rectangulo{ int ancho, largo; public: Guias de Estudio Lenguaje Orientado a Objetos, desarrolladas por: Adrin Izquierdo, docente ITP

rectangulo (int a, int l){ //constructor ancho=a; largo=l; } rectangulo (int a) { //sobrecarga del construcor para un cuadrado ancho=a; largo=a; //se asina el mismo a (ancho al largo) } float area(){ return ancho * largo; } }; main(){ rectangulo r1(20,30); //el objeto r1 al crearse llamara al primer constructor rectangulo r2(20); //el objeto r2 al crearse llamar al segundo constructor cout << "El area de r1 es " << r1.area()<< endl; cout << "El area de r2 es " << r2.area()<< endl; return 0; } El programa anterior reporta: El area de r1 es 600 El area de r2 es 400 En el programa anterior se puede notar la utilidad de la sobrecarga y en este caso sobrecarga de constructores debido a que podemos utilizar con el mismo nombre el constructor de dos maneras distintas.

Guias de Estudio Lenguaje Orientado a Objetos, desarrolladas por: Adrin Izquierdo, docente ITP

Constructor de copias: Para hablar del constructor de copias, hablemos primero de la copia superficial de objetos: Esta caracterstica consiste en la copia bit a bit de un objeto, esto sucede en las siguiente situaciones: 1. Cuando se asigna un objeto a otro 2. Cuando se pasa un objeto como parmetro por valor a una funcin 3. Cuando se devuelve un objeto como retorno de una funcin Observemos un ejemplo de copia superficial de un objeto cuando se asigna a otro: #include <iostream> using namespace std; class miclase{ int *p; public: void poner_p(int x){p=new int(x);} int traer_p(){return *p;} void quitar_p(){delete p;} }; main(){ miclase ob1, ob2; ob1.poner_p(4); ob2=ob1; cout << ob2.traer_p()<<endl; ob1.quitar_p(); cout << ob2.traer_p()<<endl; } //variable de clase tipo apuntador a entero //p localiza memoria asinando el valor de x y apunta a ella //retorna lo que hay en la localizacion de memoria //elimina la localizacin de memoria

//crea dos objetos tipo mi clase //llama a la funcion poner_p del objeto ob1 //asigna ob1 a ob2, copia superficial //Escribe 4 //Elimina la localizacin de memoria donde apunta p de ob1 //Hizo efecto en ob2, ya que escribe 0

Observemos lo que sucedi en el programa anterior analizando instruccin por instruccin: 1) miclase ob1, ob2; //Crea dos objetos tipo mi clase

2) ob1.poner_p(4);

//el apuntador p ob1 queda apuntando a una localizacin

3) ob2=ob1; misma localizacin

//asigna ob1 a ob2, pero p de ob2 queda apuntando a la

Guias de Estudio Lenguaje Orientado a Objetos, desarrolladas por: Adrin Izquierdo, docente ITP

//que p en ob1, esto es una copia superficial.

4) cout << ob2.traer_p()<<endl; //Escribe el contenido de p del objeto ob2, en este caso 4 5) ob1.quitar_p(); //Elimina la localizacin de memoria donde apunta p de ob1, esto afecta a p de //ob2

6) cout << ob2.traer_p()<<endl; //Escribe 0, esto es evidencia que ob2 se afecto por eliminar la localizacin de p en ob1. Recordando que la copia superficial de objetos sucede en los casos: 1. Cuando se asigna un objeto a otro 2. Cuando se pasa un objeto como parmetro por valor a una funcin 3. Cuando se devuelve un objeto como retorno de una funcin El denominado constructor de copias se lo ha implementado para evitar la copia superficial de objetos sobretodo para los dos ltimos casos (cuando se pasa un objeto como parmetro por valor a una funcin y cuando se devuelve dicho objeto como retorno de la funcin) . Y en el primer caso sucede slo cuando se hace la inicializacin del objeto (es decir para el ejemplo anterior, tal y como est escrito, no se podra solucionar con constructor de copias ya que la asignacin no se la hizo en la inicializacin del objeto ob2, sino que fue despus). En el proceso de copias de objetos en un constructor de copias se realiza una copia profunda. Veamos un ejemplo: #include <iostream> #include <stdlib.h> using namespace std; class arreglo{ int *p; int tamano; public: arreglo(int x){//constructor normal p=new int[x]; tamano=x; cout << "Constructor comun y corriente\n"; } ~arreglo(){delete [] p;} //destructor elimina el arreglo p Guias de Estudio Lenguaje Orientado a Objetos, desarrolladas por: Adrin Izquierdo, docente ITP

//CONSTRUCTOR DE COPIAS arreglo(const arreglo &a); void poner(int i, int j){ if(i>=0 && i<tamano) //ve si la posicion es valida p[i] = j; } int traer(int i){ return p[i]; //retorna el valor de un elemento i de p } }; /* Implementacion del constructor de copias, donde se asigna otra localizacion para p para no apuntar a una sola, sino a una diferente para cada objeto */ arreglo::arreglo (const arreglo &a){ int i; p = new int[a.tamano]; //p solicita una nueva localizacion del arreglo for (i=0; i<a.tamano; i++) p[i]=a.p[i]; //copia elemento por elemento cout << "Se esta usando el constructor de copias" << endl; } main(){ arreglo ob1(10); //Se llama al constructor normal int i; //asignacion de valores de 1 a 10 en el arreglo de ob1 for(i=0;i<10;i++) ob1.poner(i,i+1); //Escribir cada uno de los valores del arreglo de ob1 for(i=0;i<10;i++) cout << ob1.traer(i) << " "; cout << endl; //Aqui viene el uso del constructor de copias //declararemos otro objeto tipo arreglo y asingemosle el primer objeto arreglo ob2 = ob1; //se llama al constructor de copias en la asignacin con la inicializacin //ya que se est declarando un nuevo objeto tipo arreglo //para ver si es cierto cambiemos algunos elementos del objeto 2 ob2.poner(1,10); ob2.poner(5,50); ob2.poner(7,70); ob2.poner(9,90); //Escribamos nuevamente los valores del arreglo en ob1 Guias de Estudio Lenguaje Orientado a Objetos, desarrolladas por: Adrin Izquierdo, docente ITP

for(i=0;i<10;i++) cout << ob1.traer(i) << " "; cout << endl; //Ahora escribamos los valores del arreglo en ob2 //para ver si tiene diferencias con los de ob1 for(i=0;i<10;i++) cout << ob2.traer(i) << " "; cout << endl; } El programa anterior escribe lo siguiente: Constructor comun y corriente 1 2 3 4 5 6 7 8 9 10 Se esta usando el constructor de copias 1 2 3 4 5 6 7 8 9 10 1 10 3 4 5 50 7 70 9 90 Por lo tanto analizando el programa anterior, nos damos cuenta que el arreglo de ob1 y el arreglo de ob2 son diferentes, es decir estn apuntando a localizaciones diferentes, veamos la grfica de cmo se quedaron los objetos despus de llamar al constructor de copias y de cambiar algunos valores en el arreglo del objeto 2:

Ejercicios: 1. Analizando el ejemplo anterior implemente un constructor de copias para solucionar el problema visto en el primer ejemplo de esta sesin (jueves 15 de octubre), tenga en cuenta que se debe modificar el ejemplo para que cumpla con el requisito de la inicializacin en la asignacin. 2. Modifique el ltimo ejemplo para usar el constructor de copias donde se enve un objeto como parmetro a una funcin. 3. Modifique el ltimo ejemplo para usar el constructor de copias donde una funcin retorne un objeto.

Guias de Estudio Lenguaje Orientado a Objetos, desarrolladas por: Adrin Izquierdo, docente ITP

Argumentos implcitos: Los argumentos implcitos son un caso de la sobrecarga de funciones. Consisten en dar valores implcitos a parmetros cuando no se enva ningn argumento para dicho parmetro. Veamos un ejemplo: Declaremos la funcin suma() con tres parmetros y asignmosle a cada uno un valor por defecto (implcito): int suma(int x=0, int y=0, int z=0){//por defecto los parmetros toman el valor 0 si //no reciben nada return x+y+z; } Esta funcin retornara la suma de tres enteros que se le pasan como argumentos, pero esta funcin se podra llamar de varias maneras: r = suma(4, 3, 5); r = suma(4,3); r = suma(4); r = suma(); //en r quedara almacenado el valor 12 //en r quedara almacenado el valor 7 //en r quedara almacenado el valor 4 //en r quedara almacenado el valor 0

Una norma a tener en cuenta en los argumentos implcitos es que cuando en la funcin se declara algn parmetro como implcito, los dems parmetros que le siguen tambin deben tener valor implcito. Si hubiramos declarado la funcin suma de la siguiente manera, estaramos cometiendo un error: int suma(int x=0, int y, int z){// Error, y y z tambin deberan ser implcitos return x+y+z; } Por el contrario en esta declaracin no existira error: int suma(int x, int y=0, int z=0){// No hay error, despus de y todos los dems (z) son //implcitos return x+y+z; } Ejercicio: Adecu el programa de la pgina 25 de esta gua para que la funcin constructora trabaje con argumentos implcitos. Es posible que un constructor se implemente con argumentos implcitos?. Direccin de una funcin Como una variable o un objeto, una funcin tambin tiene una direccin, la cual se puede guardar en un apuntador. Veamos un ejemplo de cmo se crea un apuntador a una funcin y cmo con l apuntar a la funcin:

Guias de Estudio Lenguaje Orientado a Objetos, desarrolladas por: Adrin Izquierdo, docente ITP

#include <iostream> using namespace std; //la funcin fun devuelve un entero y recibe un char int fun(char x){ return x+1; } main(){ //declaracin de un apuntador a la funcin fun int (*p)(char); //int es el tipo que devuelve fun y char es el tipo del parmetro que recibe fun //hacer que p apunte a la funcin fun p=fun; cout << p('a') <<endl; //llamar a la funcion fun , reporta 98 } Direccin de una funcin sobrecargada Al igual que se puede apuntar a una funcin normal, como vimos en el ejemplo anterior, tambin es posible apuntar a una funcin que se sobrecarga. Hay que tener en cuenta que las funciones sobrecargadas tienen el mismo nombre, pero en realidad son distintas, por lo tanto un apuntador slo puede apuntar a una de las versiones de esas funciones, entonces si se quiere apuntar a las otras , se necesitarn otros apuntadores. El compilador sabe a que funcin sobrecargada debe apuntar un puntero, de acuerdo a cmo haya sido declarado ese puntero, porque busca el que tenga el mismo esquema de tipos de la funcin. Veamos el siguiente ejemplo: #include <iostream> using namespace std; //la funcin fun devuelve un entero y recibe un char int fun(char x){ return x; //devueve el codigo ascii } int fun(char x, int n){ return x+n; } main(){ //declaracin de un apuntador a la funcin fun int (*p)(char); //int es el tipo que devuelve fun y char es el tipo del parmetro que recibe fun int (*q)(char, int); //int es el tipo que devuelve fun y char e int son el tipo del parmetro que recibe //fun //hacer que p apunte a la funcin fun p=fun; cout << p('a') <<endl; //llamar a la funcion fun version 1 , reporta 97

Guias de Estudio Lenguaje Orientado a Objetos, desarrolladas por: Adrin Izquierdo, docente ITP

//hacer que q apunte a fun version2 q=fun; cout << q('a',5) <<endl; //lamar a la funcion fun version2, reporta 102 } Ejercicio: Realice un ejemplo para que trabaje con funciones sobrecargadas de un objeto. Es esto posible? Respuesta: Tal y como hemos visto la asignacin de una funcin a un puntero, no es posible hacerlo, pero se puede lograr haciendo que el puntero sea del tipo de clase en cuestin. La forma de hacerlo es: tipo (clase::*apuntador)(tipo_parmetros)=&clase::funcin; donde: tipo: es el tipo de datos que retorna la funcin de clase clase: es el nombre de la clase apuntador: nombre que se le asignar al apuntador tipo_parmetros: son los tipos de datos de los parmetros de la funcin miembro funcin: es el nombre de la funcin miembro a la cual se va apuntar En el esquema anteriormente visto se declara el apuntador y ah mismo se especifica que apunte a la funcin miembro. Para llamar a una funcin miembro por medio de su apuntador, se realiza el siguiente esquema (objeto.*apuntador)(argumentos); donde: objeto: es una instancia de la clase, con la que tambin se declar el apuntador a funcin apuntador: es el apuntador de la funcin miembro argumentos: son los valores que se le enva a la funcin. veamos cmo se resuelve mediante el ejemplo de la clase rectngulo. #include <iostream> using namespace std; class rectangulo{ float largo, ancho; float area; public: void medidas(float x, float y){ //version 1 largo=x; ancho=y; } void medidas(float x){ //version 2 -- sobrecarga largo=x; ancho=x; Guias de Estudio Lenguaje Orientado a Objetos, desarrolladas por: Adrin Izquierdo, docente ITP

} float traer_area(){ area=largo*ancho; return area; } }; main(){ //Declaracion de dos objetos tipo rectangulo rectangulo r1, r2; //declaramos el apuntador a funcin de clase y le asignamos la funcin a la que //apuntara, es muy importante el molde ya que la funcin est sobrecargada void (rectangulo::*pRect)(float, float)=&rectangulo::medidas; (r1.*pRect)(3.5, 5.4); //llamar a la funcion medidas (version1) de r1 cout <<r1.traer_area()<<endl; //Escribe el area 18.9 //declaramos el apuntador a funcion de clase y le asignamos la funcion a la que //apuntara, es muy importante el molde ya que la funcion est sobrecargada void (rectangulo::*pCuad)(float)=&rectangulo::medidas; (r2.*pCuad)(4.5); // cout <<r2.traer_area()<<endl; //Escribe el area 20.25 }

Guias de Estudio Lenguaje Orientado a Objetos, desarrolladas por: Adrin Izquierdo, docente ITP

SOBRECARGA DE OPERADORES La sobrecarga de operadores es de alguna manera un tipo de sobrecarga de funciones y se utilizan para simplificar operaciones entre objetos. Si tenemos la clase Perro (del mdulo de la UOC Introduccin al Desarrollo de Software) y se quisiera incrementar en uno la edad de un objeto perro, sera posible realizar una funcin de clase para ello: class Perro { int edad; int altura; public: Perro(int nEdad, int nAltura){ edad = nEdad; altura = nAltura; } void incEdad(){edad++;} //Funcin que hace que se incremente la edad de un perro en 1 int traer_edad(){return edad;} int traer_altura(){return altura;} }; //En este caso para incrementar la edad de un perro en 1, se necesita llamar a la funcin miembro de //la clase Perro llamada incEdad main(){ Perro tony(12, 95); //creamos un objeto tony con edad 12 aos y 95cm de estatura tony.incEdad(); //incrementamos la edad en 1 del objeto tony cout << tony.traer_edad()<<endl; //Debe escribir 13 return 0; } Si observamos el programa anterior todava no hemos utilizado la sobrecarga de operadores, nada ms se ha llamado a una funcin para incrementar la edad de un perro. Pero resulta que este manejo es inapropiado ya que se puede realizar mediante la sobrecarga de operadores. En este caso vamos a sobrecargar el operador ++. Antes de hacerlo es necesario aclarar que en C++ es posible sobrecargar casi cualquier operador excepto . :: .* ? Para mayor informacin ingrese a http://www.zator.com/Cpp/E4_9_18.htm Antes de realizar la sobrecarga del operador ++ del ejemplo tenemos que estudiar que son los operadores unarios y operadores binarios: Unarios: Son operadores que necesitan slo un operando para funcionar, por ejemplo, el operador ++ slo necesita un operando, por ejemplo a++; //solo se necesit un operando, la variable a o tambin ++a; Binarios: Son operadores que necesitan estar en medio de dos operandos, por ejemplo: a + b; //El operador + necesita estar en medio de dos variables a y b La sobrecarga del operador se declara de la misma forma que una funcin. Se utiliza la palabra reservada operator, seguida del operador que se va a sobrecargar. En el caso de las funciones de Guias de Estudio Lenguaje Orientado a Objetos, desarrolladas por: Adrin Izquierdo, docente ITP

operadores unarios, no llevan parmetros (a excepcin del incremento o decremento postfijo que utilizan un entero como diferenciador). Veamos cmo sobrecargamos el operador unario ++ en la clase Perro: class Perro { int edad; public: Perro(int nEdad) {edad = nEdad;} Perro operator++(); // Cuando el operador precede, ej: ++ob Perro operator++(int); // Cuando el operador va al final, ej: ob++ int traer_edad(){return edad;} }; //implementacion cuando el operador precede al operando Perro Perro::operator++() { ++edad; return (*this); } //implementacion cuando el operador va al final del operando Perro Perro::operator++(int x) { Perro temp = *this; ++edad; return (temp); } int main() { Perro tony(12); cout << "Edad de Tony al comenzar el programa \n " ; cout << tony.traer_edad() << endl; ++tony; //uso del operador ++ sobrecargado cout << "Edad de Tony despus de un aniversario \n "; cout << tony.traer_edad() << endl; ++tony; //uso del operador ++ sobrecargado cout << "Edad de Tony despus de otro aniversario\n"; cout << tony.traer_edad() <<endl; } El anterior programa escribe: Edad de Tony al comenzar el programa 12 Edad de Tony despus de un aniversario 13 Edad de Tony despus de otro aniversario 14 Sobrecarga de operadores binarios:

Guias de Estudio Lenguaje Orientado a Objetos, desarrolladas por: Adrin Izquierdo, docente ITP

Cuando se sobrecarga un operador binario, la funcin recibe un slo parmetro, este parmetro tomar al objeto del lado derecho y el objeto del lado izquierdo es el que llama a la funcin constructora el cual se pasa explcitamente por medio del objeto this. Ahora realizaremos un ejemplo para sobrecargar un operador binario: #include <iostream> using namespace std; class punto{ float x, y; // valores de un punto en 2D public: punto(){x=0; y=0;} punto(float a, float b){x=a; y=b;} float traer_x(){return x;} float traer_y(){return y;} punto operator+(punto ob2); // + se sobrecarga recibiendo en ob2 el objeto de la derecha // el objeto de la derecha se recibe con this ya que es el que //realiza el llamado }; punto punto::operator+(punto ob2){ punto aux; aux.x = x + ob2.x; aux.y = y + ob2.y; return aux; } main(){ punto p1(3.5, 2.5); punto p2(4.5, 6.5); punto p3; p3 = p1 + p2; //se llama al operador sobrecargado de + cout <<"Los valores de p3 en x son" << p3.traer_x()<<endl; cout <<"Los valores de p3 en y son" << p3.traer_y()<<endl; return 0; } Ejercicios: 1. Tomando como base el ejemplo anterior sobrecargue los operadores ==, <, <=, >, >= para determinar si la suma de los valores de x y y de un punto es igual, menor, menor o igual, mayor , mayor o igual a la suma de los valores de x y y de otro punto. El valor devuelto en cada caso debe ser un bool (true o false). Por ejemplo al comparar: if (p1 == p2), el resultado debe ser false ya que 6 no es igual a 11.

Guias de Estudio Lenguaje Orientado a Objetos, desarrolladas por: Adrin Izquierdo, docente ITP

LA HERENCIA Herencia simple: La programacin orientada a objetos pretende simular caractersticas de la vida como es la herencia. Con la herencia es posible reducir el cdigo considerablemente y adems tener una mejor comprensin de los programas ya que sern ms intuitivos debido a que es posible crear jerarquas entre clases. Para comprender la herencia basta con citar un ejemplo sencillo como el siguiente: si tenemos dos animales como un perro y un gato podramos clasificarlos dentro de un mismo grupo llamado mamferos, por lo tanto ambos compartirn las mismas caractersticas bsicas de un mamfero:

Mamfero
__________________________________

Extremidades: 4 Respiracin: Aire Dientes: Si Pelo: Si Sangre: Caliente Reproduccin: Vivpera Fecundacin: Interna

Perro
_________________________

Gato
_________________________

Nombre: Tony Raza_perro: Pastor Tamao: 1 metro Peso: 15 Kgs

Nombre: Micif Raza_gato: Angora Tamao: 0.3 metros Peso: 2 Kgs

Cuando se quiera indagar acerca del perro tony, es posible ver sus caractersticas propias como su nombre, su raza su tamao y peso; pero adems sus caractersticas como mamfero como el tipo de respiracin, si tiene dientes, pelo etc. Aqu hemos visto un ejemplo de herencia muy bsico, pero se podra extender ms an, por ejemplo todos los mamferos son seres vivos, entre los seres vivos existen reinos:

http://www.juntadeandalucia.es/averroes/colegiolasalud/spip/local/cache-vignettes/L520xH340/los_seres_vivos-75f62.jpg

Guias de Estudio Lenguaje Orientado a Objetos, desarrolladas por: Adrin Izquierdo, docente ITP

Implementacin de la herencia Para expresar esta relacin en C++, en la declaracin de una clase despus de su nombre se pone dos puntos (:), el tipo de derivacin (pblica, protegida o privada) y el nombre de la clase de la cual deriva. class clase_derivada: TipoDerivacion clase_base Ej: class Perro : public Mamifero Tipo de Derivaci Clase derivada: n Es el nombre de la clase que se est creando, en este caso Perro Dos puntos Tipo de derivacin Existe tres tipos de derivacin: public, protected y private. El tipo de acceso a la clase base especifica cmo recibir la clase derivada a los miembros de la clase base. Si no se especifica un acceso a la clase base, C++ supone que su tipo de herencia es privado. - public: Todos los miembros public y protected de la clase base son accesibles en la clase derivada, mientras que los miembros private de la clase base son siempre inaccesibles en la clase derivada. - private: Todos los miembros de la clase base se comportan como miembros privados de la clase derivada. Los miembros public y protected de la clase base sern privados en clase derivada. Los miembros privados de la clase siguen siendo inaccesibles desde la clase derivada. - protected: Los miembros public y protected de la clase base se comportan como miembros protected de la clase derivada. Estos miembros no son, pues, accesibles al programa exterior, pero las clases que se deriven a continuacin podrn acceder normalmente a estos miembros (datos o funciones). Clase base: Es la clase que se hereda, en este caso Mamifero. Una regla general de diseo recomienda mantener los datos miembro como privados, y manipularlos a travs de funciones pblicas de acceso donde se obtiene o se le asigna un valor. #include <iostream> using namespace std; enum RAZAS { PASTOR_ALEMAN, DOBERMAN, ANGORA, COMUN }; class Mamifero { protected: int edad; public: Mamifero(){}; // mtodo constructor ~Mamifero(){}; // mtodo destructor void asignarEdad(int nEdad) { edad = nEdad; } //mtodo comn int obtenerEdad() { return (edad); } //mtodo comn }; class Perro : public Mamifero //hereda de Mamifero Clase derivada Clase base

Guias de Estudio Lenguaje Orientado a Objetos, desarrolladas por: Adrin Izquierdo, docente ITP

{ public: Perro(){}; // mtodo constructor ~Perro(){}; // mtodo destructor void asignarRaza(RAZAS r){raza =r;} //mtodo propio de la clase perro int obtenerRaza(){return raza;} //mtodo propio de la clase perro void ladrar() { cout << "Guau " << endl; }; //mtodo propio de la clase perro private: RAZAS raza; //variable de clase propia de la clase perro }; class Gato : public Mamifero //hereda de Mamifero { public: Gato(){}; // mtodo constructor ~Gato(){}; // mtodo destructor void asignarRaza(RAZAS r){raza =r;} //mtodo propio de la clase gato int obtenerRaza(){return raza;} //mtodo propio de la clase gato void maullar() { cout << "Miauuu" << endl; } //mtodo propio de la clase gato private: RAZAS raza; //variable de clase propia de la clase gato }; main(){ Perro Tony; Gato Micifu; Tony.asignarEdad(13); cout << "La edad de tony es: " << Tony.obtenerEdad() << endl; Tony.asignarRaza(PASTOR_ALEMAN); cout << "La Raza de tony es: " << Tony.obtenerRaza() << endl; Tony.ladrar(); Micifu.asignarEdad(3); cout << "La edad de Micifu es: " << Micifu.obtenerEdad() << endl; Micifu.asignarRaza(ANGORA); cout << "La Raza de Micifu es: " << Micifu.obtenerRaza() << endl; Micifu.maullar(); } Este programa reporta: La edad de tony es: 13 La Raza de tony es: 0 Guau La edad de Micifu es: 3 La Raza de Micifu es: 2 Miauuu Nota: En el ejemplo anterior trabajamos un tema que no habamos tocado antes, las enumeraciones, en este caso la enumeracin RAZAS: enum RAZAS { PASTOR_ALEMAN, DOBERMAN, ANGORA, COMUN }; Guias de Estudio Lenguaje Orientado a Objetos, desarrolladas por: Adrin Izquierdo, docente ITP

donde PASTOR_ALEMAN toma el valor 0, DOBERMAN el valor 1, ANGORA el valor 2 y COMUN el valor 3. Para ms informacin de enumeraciones es posible visitar: http://www.programacion-ard.com/enumeraciones_c.php Ejercicio: En el ejemplo anterior hay mtodos que han sido creados como propios de cada clase como asignarRaza y obtnerRaza. Modifquelos para que sean mtodos comunes, es decir, que aparezcan en la clase base y se puedan heredar. Hay mejora en el cdigo? Por qu? Constructores y destructores de clases derivadas A la hora de crear un objeto derivado de una clase base suceden las siguientes situaciones: Cuando se crea el objeto derivado, por ejemplo el perro tony, primero se llaman a los constructores de la clase base en este caso Mamifero() y luego se llama a los constructores de la clase derivada, en este caso Perro(). mamifero() perro()
Proceso de creacin de un objeto derivado, llamadas a constructores

Cuando se destruye el objeto derivado, en este caso tony, el proceso es al contrario, primero se llama al destructor de perro y luego al destructor de mamfero ~perro() ~mamifero()
Proceso de destruccin de un objeto derivado

Redefinicin de mtodos Cuando hay mtodos comunes en la clase base, es posible redefinirlos para cada clase derivada en particular. En las clases derivadas que no se redefina el mtodo, estas trabajarn con el mtodo comn (el de la clase base). Nota: La redefinicin de mtodos no es lo mismo que la sobrecarga de mtodos o funciones. En la redefinicin no se sobrecarga debido a que se toma la funcin tal y como se defini en la clase base. Recordemos que en la sobrecarga existe algn elemento que debe variar como: el nmero de parmetros, el tipo de los parmetros... Si tomamos las clases del ejemplo anterior y creamos un mtodo comn llamado emite_sonido en la clase base: #include <iostream> using namespace std; enum RAZAS { PASTOR_ALEMAN, DOBERMAN, ANGORA, COMUN }; class Mamifero { protected: int edad; public: Guias de Estudio Lenguaje Orientado a Objetos, desarrolladas por: Adrin Izquierdo, docente ITP

Mamifero(){}; // mtodo constructor ~Mamifero(){}; // mtodo destructor void asignarEdad(int nEdad) { edad = nEdad; } //mtodo comn int obtenerEdad() { return (edad); } //mtodo comn void emite_sonido () { cout << "Sonido" << endl ;} //mtodo comn }; class Perro : public Mamifero //hereda de Mamifero { public: Perro(){}; // mtodo constructor ~Perro(){}; // mtodo destructor void asignarRaza(RAZAS r){raza =r;} //mtodo propio de la clase perro int obtenerRaza(){return raza;} //mtodo propio de la clase perro void ladrar() { cout << "Guau " << endl; }; //mtodo propio de la clase perro void emite_sonido () { cout << "Ladrido" << endl ;} //mtodo redefinido private: RAZAS raza; //variable de clase propia de la clase perro }; class Gato : public Mamifero //hereda de Mamifero { public: Gato(){}; // mtodo constructor ~Gato(){}; // mtodo destructor void asignarRaza(RAZAS r){raza =r;} //mtodo propio de la clase gato int obtenerRaza(){return raza;} //mtodo propio de la clase gato void maullar() { cout << "Miauuu" << endl; } //mtodo propio de la clase gato private: RAZAS raza; //variable de clase propia de la clase gato }; main(){ Mamifero mam; //objeto tipo Mamifero, es independiente Perro Tony; Gato Micifu; mam.emite_sonido(); //Escribe sonido, ya que lo invoca un objeto de //tipo mamifero Tony.asignarEdad(13); cout << "La edad de tony es: " << Tony.obtenerEdad() << endl; Guias de Estudio Lenguaje Orientado a Objetos, desarrolladas por: Adrin Izquierdo, docente ITP

Tony.asignarRaza(PASTOR_ALEMAN); cout << "La Raza de tony es: " << Tony.obtenerRaza() << endl; Tony.ladrar(); Tony.emite_sonido(); //Escribe Ladrido, porque se redefinio Micifu.asignarEdad(3); cout << "La edad de Micifu es: " << Micifu.obtenerEdad() << endl; Micifu.asignarRaza(ANGORA); cout << "La Raza de Micifu es: " << Micifu.obtenerRaza() << endl; Micifu.maullar(); Micifu.emite_sonido();//Escribe Sonido, ya que no se redefinio } Este programa reporta la siguiente informacin: Sonido La edad de tony es: 13 La Raza de tony es: 0 Guau Ladrido La edad de Micifu es: 3 La Raza de Micifu es: 2 Miauuu Sonido Aqu en la clase Perro se redefini el mtodo emite_sonido, lo que quiere decir que si un objeto Perro llama a este mtodo, se utilizar el mtodo redefinido, en este caso hace que se escriba la palabra Ladrido. En la clase Gato no se redefini el mtodo emite_sonido, por lo tanto, los objetos de esta clase, cuando llamen al mtodo emite_sonido, lo harn de la clase base, por eso se escribe la palabra Sonido. Cuando se redefine una funcin en una clase derivada se oculta la funcin de la clase derivada (Como en el caso de la funcin emite_sonido en Perro, se oculta la funcion emite_sonido de Mamifero) y su hubieran sobrecargas de la funcin en la clase base, estas tambin quedaran ocultas en la clase derivada que redefini la funcin, por lo tanto si se quiere sobrecargas de la funcin redefinida, estas sobrecargas deberan realizarse en la clase derivada. Sin embargo, si se necesita acceder a la funcin ocultada (por la redefinicin) es posible hacerlo utilizando la siguiente sintaxis para el llamado: objeto_derivado.ClaseBase::metodo_comun(); por ejemplo: tony.Mamifero::emite_sonido(); // escribir Sonido Ejercicio: Compruebe como se puede acceder a una funcin ocultada por redefinicin utilizando el ejemplo visto.

Guias de Estudio Lenguaje Orientado a Objetos, desarrolladas por: Adrin Izquierdo, docente ITP

Paso de argumentos a un constructor desde una clase derivada a una clase base Cuando se trabaja con herencia en ocasiones es necesario pasar argumentos desde la clase derivada a una clase base: Ejemplo: #include <iostream.h> using namespace std; class base{ int i; public: base (int n){ i=n; } void mostrar_i(){cout << i << \n; } }; class derivada: public base { //hereda los miembros publicos y protegidos int j; public: derivada(int n, int m) : base(n) { //se pasa el argumento n a la clase base j=m; } void mostrar_j(){cout << j << endl;} }; main(){ derivada d(20, 30); d.mostrar_i(); //Escribe 20 d.mostrar_j(); //Escribe 30 } Herencia Mltiple: Existen dos modos de herencia mltiple: A) Cuando una clase base derivada puede ser usada como la clase base de otra clase derivada: En este caso se crea una jerarqua de clases multiniveles. Ej: class Base{ int a; public: Base (int x){ a = x;} int traer_a () {return a;} }; class Der1: public Base { //Herencia directa de Base a Der1 int b; public: Der1(int x, int y) : Base (y) //paso de y al constructor de Base { Guias de Estudio Lenguaje Orientado a Objetos, desarrolladas por: Adrin Izquierdo, docente ITP

b=x; } int traer_b(){ return b;} }; //Herencia indirecta de una clase derivada y de una base indirecta class Der2: public Der1 { int c; public: Der2(int x, int y, int z) : Der1(y, z) //Paso de argumentos a Der1 { c=x; } /*Debido a que las bases se heredan como pblicas, Der2 tiene acceso a los elementos publicos de Der1 y Base */ void mostrar(){ cout << traer_a() << << traer_b() << ; cout << c << endl; } }; main (){ Der2 obj(5, 4, 3); obj.mostrar(); //Escribe 5 4 y 3 //traer_a y traer_b siguen siendo publicos aqu cout << traer_a() << << traer_b() << endl; //Escribe 5 y 4 } En este caso la jerarqua de clases se graficara as Base Der1 Der2 B) Cuando una clase derivada hereda directamente ms de una clase base. Una clase derivada puede heredar directamente ms de una clase base con la siguiente sintaxis: class derivada : tipo_acceso base1, tipo_acceso base2, tipo_acceso base3, , tipo_acceso baseN Ejemplo: //Una clase base class Base1{ int a; public: Base1 (int x){ a = x;} int traer_a () {return a;} }; //Otra clase base Guias de Estudio Lenguaje Orientado a Objetos, desarrolladas por: Adrin Izquierdo, docente ITP

class Base2{ int b; public: Base2 (int x){ b = x;} int traer_b () {return b;} }; class Der: public Base1, public Base2{ int c; public: //En la creacion del constructor se pasa z a Base1 y y a Base2 D(int x, int y, int z): Base1(z), Base2(y) { c = x; } //Se tiene acceso a los miembros publicos de Base1 y Base2 void mostrar(){ cout << traer_a() << ' ' << traer_b() << ' ' << c << endl; } }; main(){ Der obj( 3, 6, 9); obj.mostrar(); //Escribe 3 6 9 } La grafica de la herencia sera as: Base1 Der Ejercicio: Investigue en qu consisten las Clases Bases Virtuales Base2

Guias de Estudio Lenguaje Orientado a Objetos, desarrolladas por: Adrin Izquierdo, docente ITP

EL POLIMORFISMO La potencia de un lenguaje orientado a objetos como el C++ radica en gran medida al uso del polimorfismo. El polimorfismo consiste en conseguir que un objeto de una clase se comporte como un objeto de cualquiera de sus subclases. Para conseguir esto se utilizan punteros de tipo de la clase base, los cuales pueden apuntar cualquiera de los objetos de las clases derivadas. Por ejemplo a un apuntador de tipo Mamifero se le puede asignar un objeto de tipo Perro: Mamifero *p = new Perro; O tambin Perro tony; Gato micifu; Mamifero *p; p = &tony; //p apunta al objeto tony de la clase derivada Perro p= &micifu; //p apunta al objeto micifu de la clase derivada Gato Si se quisiera acceder a las funciones miembro de cada clase derivada por medio de un apuntador de tipo base (polimorfismo) no se puede hacer directamente, para esto se crearon las funciones virtuales que veremos ms adelante. Perro tony; p = &tony; //p apunta al objeto tony de la clase derivada Perro p->asignar_edad(12); //no es posible ya que p solo puede acceder a las funciones de la clase base Lo importante del polimorfismo es que se puede lograr en tiempo de ejecucin, es decir, el programador podra no tener certeza a qu objeto de la clase derivada se va a apuntar, ya que dependera de la ejecucin del programa. Por ejemplo en un juego si se tiene una clase base llamada enemigo y clases derivadas enemigo_ninja, enemigo_monstruo, enemigo_robot. Dependiendo del contexto o el nivel del juego, un apuntador de tipo enemigo podra tomar en un momento determinado una forma diferente apuntado a un objeto de la subclase. Esto hace que se ahorre mucho cdigo y los programas sean ms entendibles para los diseadores y programadores debido a que se usa la programacin de manera ms parecida a la realidad. class enemigo{ //clase base ... }; class enemigo_ninja : public enemigo{ //clase derivada de enemigo }; class enemigo_monstruo : public enemigo{//clase derivada de enemigo }; class enemigo_robot : public enemigo{//clase derivada de enemigo };

Guias de Estudio Lenguaje Orientado a Objetos, desarrolladas por: Adrin Izquierdo, docente ITP

main(){ enemigo *apuntad= new enemigo_monstruo; ... }

enemigo_ninja enemigo_monstruo enemigo * apuntad enemigo_robot


polimorfismo:apuntad apunta a enemigo_monstruo y podra apuntar a cualquier objeto derivado de enemigo

FUNCIONES VIRTUALES Una funcin virtual es un miembro de una clase que se declara dentro de una clase base y se redefine en una clase derivada. Las funciones virtuales se preceden con la palabra clave virtual dentro de la clase base, en la clase derivada no es necesaria esta palabra, aunque puede ir para recordarnos que es una funcin virtual. Las funciones virtuales fueron creadas para que C++ soporte el polimorfismo, y por tanto estas se llaman por medio de apuntadores. Ejemplo: #include <iostream> using namespace std; class base { public: int i; base (int x) {i = x;} virtual void funcionV(){ //Declaracion de una funcin virtual cout << "Uso de la funcion virtuale en la base " << endl; cout << i << endl; } }; class der1 : public base{ public: der1 (int x): base(x) {} void funcionV(){ //Redefinicion de la funcion virtual cout << "Uso de la funcion virtual en la clase der1 "; cout << i+i << endl; Guias de Estudio Lenguaje Orientado a Objetos, desarrolladas por: Adrin Izquierdo, docente ITP

} }; class der2 : public base{ public: der2 (int x): base(x) {} void funcionV(){ //Redefinicion de la funcion virtual cout << "Uso de la funcion virtual en la clase der2 "; cout << i*i << endl; } }; main (){ base *p; //apuntador de tipo base puede apuntar a los objetos que heredan de base base ob (15); //objeto tipo base der1 dob1 (20); //objeto tipo der1 que hereda de base der2 dob2 (25); //objeto tipo der2 que hereda de base p=&ob; //p apunta al objeto de tipo base ob p->funcionV(); //se llama a la funcion virtual p=& dob1; //apunta ahora al objeto derivado dob1 p->funcionV(); //se llama a la funcion virtual p=& dob2; //apunta ahora al objeto derivado dob2 p->funcionV(); //se llama a la funcion virtual } El programa anterior escribe: Uso de la funcion virtuale en la base 15 Uso de la funcion virtual en la clase der1 40 Uso de la funcion virtual en la clase der2 625 En el caso del ejemplo del juego del enemigo, si hubieran acciones similares entre los diferentes tipos de enemigos, se podran agrupar y definirlas como virtuales dentro de la clase base, y luego en cada subclase redefinirlas para que existan cambios; por ejemplo si existiera el mtodo saltar(), este se podra aplicar a todo tipo de enemigo, pero cada enemigo podra tener su propio modo de saltar, puede ser que el tipo de enemigo ninja salte ms alto que el tipo de enemigo monstruo y enemigo robot, veamos: class enemigo{ //clase base protected int brinco; virtual void saltar(){brinco =30; brincar();} //Un enemigo que no redefina saltar, saltar 30 }; class enemigo_ninja : public enemigo{ //clase derivada de enemigo virtual void saltar(){brinco =50; brincar();} //Un enemigo ninja, saltar 50, se redefini }; class enemigo_monstruo : public enemigo{//clase derivada de enemigo Guias de Estudio Lenguaje Orientado a Objetos, desarrolladas por: Adrin Izquierdo, docente ITP

}; class enemigo_robot : public enemigo{//clase derivada de enemigo }; main(){ enemigo *apuntad; enemigo_ninja en; //crea un objeto tipo enemigo_ninja enemigo_robot er; //crea un objeto tipo enemigo_robot enemigo_monstruo em; //crea un objeto tipo enemigo_monstruo apuntad = &en; //apunta a un objeto tipo enemigo_ninja apuntad->saltar(); //saltara 50, porque se redefini saltar en la subclase enemigo_ninja apuntad = &er; //apunta a un objeto tipo enemigo_robot apuntad->saltar(); //saltara 30, porque no se redefini saltar, por lo tanto usa saltar de la base apuntad = &em; //apunta a un objeto tipo enemigo_monstruo apuntad->saltar(); //saltara 30, porque en enemigo_robot no se redefini la funcin saltar ... } Es importante aclarar que un apuntador de tipo de clase base puede apuntar a un objeto de una subclase (o clase derivada) pero que directamente no puede llamar a funciones propias de la subclase, para poder hacerlo es necesario que las funciones sean declaradas como virtuales en la clase base y luego, si se necesita, redefinir estas funciones virtuales en cada subclase. Esto es la escencia del Polimorfismo!!!. Veamos el ejemplo con las clases Mamifero y sus derivadas Perro y Gato cmo implementamos el polimorfismo: #include <iostream> using namespace std; enum RAZAS { PASTOR_ALEMAN, DOBERMAN, ANGORA, COMUN }; class Mamifero { protected: int edad; RAZAS raza; public: Mamifero(){}; ~Mamifero(){}; void asignarEdad(int nEdad) { edad = nEdad; } int obtenerEdad() { return (edad); } void asignarRaza(RAZAS r){raza =r;} int obtenerRaza(){return raza;} //mtodo virtual, se puede redefinir en las funciones que se necesite virtual void emite_sonido () { cout << "Sonido" << endl ;} //mtodo comn };

Guias de Estudio Lenguaje Orientado a Objetos, desarrolladas por: Adrin Izquierdo, docente ITP

class Perro : public Mamifero //hereda de Mamifero lo publico y protegido { public: Perro(){}; ~Perro(){}; void ladrar() { cout << "Guau " << endl; }; //mtodo propio de la clase gato virtual void emite_sonido () { cout << "Ladrido" << endl ;} //mtodo virtual redefinido }; class Gato : public Mamifero //hereda de Mamifero lo publico y protegido { public: Gato(){}; ~Gato(){}; void maullar() { cout << "Miauuu" << endl; } //mtodo propio de la clase gato virtual void emite_sonido () { cout << "Maullido" << endl ;} //mtodo virtual redefinido }; main(){ Mamifero *p; //apuntador de tipo Mamifero Perro Tony; //Objeto de tipo Perro Gato Micifu; //Objeto de tipo Gato p = &Tony; //p apunta al objeto Tony de la subclase Perro p->asignarEdad(13); //p puede llamar a la funcion asignarEdad porque es funcion de la clase base cout << "La edad de tony es: " << p->obtenerEdad() << endl;//lo mismo sucede con la funcion obtener edad p->asignarRaza(PASTOR_ALEMAN);//p puede llamar a la funcion asignarRaza porque es funcion de la clase base cout << "La Raza de tony es: " << p->obtenerRaza() << endl; //p->ladrar(); //p no puede llamar a la funcion ladrar porque es funcion de la subclase Perro Tony.ladrar(); //para hacerlo es necesario utilizar el propio objeto (No es polimorfismo) p->emite_sonido(); //p si puede llamar a emite_sonido ya que es una funcion virtual //si hay Polimorfismo p = &Micifu; //p apunta al objeto Micifu de la subclas Gato p->asignarEdad(3); //p puede llamar a la funcion asignarEdad porque es funcion de la clase base cout << "La edad de Micifu es: " << p->obtenerEdad() << endl; //lo mismo sucede con la funcion obtener edad p->asignarRaza(ANGORA);//p puede llamar a la funcion asignarRaza porque es funcion de la clase base cout << "La Raza de Micifu es: " << p->obtenerRaza() << endl; //p->maullar(); //p no puede llamar a la funcion maullar porque es funcion de la subclase Gato Micifu.maullar(); //para hacerlo es necesario utilizar el propio objeto (No es polimorfismo) p->emite_sonido(); //p si puede llamar a emite_sonido ya que es una funcion virtual //si hay Polimorfismo Guias de Estudio Lenguaje Orientado a Objetos, desarrolladas por: Adrin Izquierdo, docente ITP

} Ejercicios: 1. Cree un programa que cree una clase base llamada distancia, que almacene la distancia entre dos puntos en una variable double. En distancia, cree una funcin virtual llamada v_tiempo() que obtenga el tiempo en recorrer esa distancia, asumiendo que la distancia est en millas y que la velocidad es 60 millas por hora. En una clase derivada llamada metrica, se redefine v_tiempo() de modo que obtenga el tiempo del recorrido asumiendo que la distancia est en kilometros y que la velocidad es de 100 kilometros por hora.

Guias de Estudio Lenguaje Orientado a Objetos, desarrolladas por: Adrin Izquierdo, docente ITP

Tipos de Datos Abstractos y Funciones virtuales puras En ocasiones, no se necesita generar objetos de una clase base, por lo tanto este tipo de clases pueden ser abstractas, es decir se definen, en la clase base, mtodos y variables slo para que sean heredadas por subclases e implementar el Polimorfismo. Para lograr esto es necesario que en la clase base se declare al menos una funcin como funcin virtual pura. Declarar una funcin virtual pura se logra declarando la funcin virtual e igualndola a cero. Sintaxis: virtual tipo nombre_funcion(lista_parametros)=0; ejemplos: virtual void emiteSonido() = 0; virtual void saltar(int x) = 0; En la clase base una funcin virtual pura no se implementa, solo es necesario su prototipo (e igualarla a cero) Si se declara una o ms funciones virtuales puras, estas se heredan. Por tal motivo, en las clases derivas se deben redefinir las funciones virtuales puras. De lo contrario, la clase derivada se convierte tambin en otra clase abstracta, lo que quiere decir que no podremos crear objetos con dichas clases. Veamos el ejemplo con la clase Mamifero: #include <iostream> using namespace std; class Mamifero { protected: int edad; public: Mamifero(){}; ~Mamifero(){}; void asignarEdad(int nEdad) { edad = nEdad; } int obtenerEdad() { return (edad); } //mtodo virtual, se tiene que redefinir en las clases derivadas virtual void emite_sonido () = 0; //funcion virtual pura }; class Perro : public Mamifero //hereda de Mamifero lo publico y protegido { public: Perro(){}; ~Perro(){}; virtual void emite_sonido () { cout << "Ladrido" << endl ;} //mtodo virtual puro redefinido }; Guias de Estudio Lenguaje Orientado a Objetos, desarrolladas por: Adrin Izquierdo, docente ITP

class Gato : public Mamifero //hereda de Mamifero lo publico y protegido { public: Gato(){}; ~Gato(){}; virtual void emite_sonido () { cout << "Maullido" << endl ;} //mtodo virtual puro redefinido }; main(){ Mamifero *p; Perro Tony; Gato Micifu; p = &Tony; p->asignarEdad(13); cout << "La edad de tony es: " << p->obtenerEdad() << endl; p->emite_sonido(); //llamado a la funcion virtual pura p = &Micifu; p->asignarEdad(3); cout << "La edad de Micifu es: " << p->obtenerEdad() << endl; p->emite_sonido(); //llamado a la funcion virtual pura } Ejercicios: 1. Explique por qu no se pueden crear objetos utilizando una clase abstracta, adems cree un programa e intente hacerlo, apunte los errores que esto puede generar. 2. Investigue qu tipo de funciones no pueden ser virtuales y realice un programa para demostrarlo; apunte los errores que esto pueda generar. Uso de las bibliotecas en C++ Para dar una mejor organizacin un programa en C++, para cada clase se crea dos archivos: a) el primero es el archivo de biblioteca .hpp, donde estn todas la definiciones b) el archivo de implementacin de la clase con extensin .cpp Por ejemplo para clase Perro que hemos trabajado, estos seran los archivos //Archivo de biblioteca Perro.hpp class Perro { private: int edad; int altura; public: Perro(); //mtodo constructor int obtenerEdad(); int asignarEdad(int); Guias de Estudio Lenguaje Orientado a Objetos, desarrolladas por: Adrin Izquierdo, docente ITP

int asignarAltura(int); int obtenerAltura(); void ladrar(); }; //Archivo de implementacin de las funciones Perro.cpp #include <iostream> //necesaria para el cout #include <Perro.hpp> //inclusin de la librera Perro:Perro() {edad=0;} Perro:: ladrar() { cout << "Guau" <<endl; } void Perro:: asignarAltura (int nAltura) { altura = nAltura; } int Perro:: obtenerAltura (int nAltura) { return (altura); } void Perro:: asignarEdad (int nEdad) { edad = nEdad; } int Perro:: obtenerEdad () { return (edad); } De esta forma deben organizarse todas las clases que se creen. Para llamar a una clase, desde el programa principal, o desde dentro de otro archivo, es necesario incluir la librera de la clase, veamos, si tenemos otro archivo llamado Principal.cpp, donde est el main: //archivo Principal.cpp #include <Perro.hpp> //llamado a la librera de la clase para que se reconozca en esta funcin int main() { //Inicializando el objeto con edad 4. Perro Tony; Tony.asignar_edad(12); Tony.asignar_altura(80); cout << La edad del perro es << Tony.obtener_Edad() << endl; Tony.ladrar(); } Biblioteca STL La biblioteca STL (Biblioteca Estndar de Plantillas) fue desarrolladas por Alex Stepanov en los laboratorios HP y puesta por Hewlett Packard en el dominio pblico. STL es un conjunto de procedimientos que nos facilitan el trabajo en C++, ya que en ella viene implementado una serie de funciones importantes como el manejo de Pilas, Listas, Conjuntos, Vectores, Arboles Binarios, etc. Libros gratis de internet donde pueden encontrar ms informacin acerca de estas libreras son: C++ STL, Plantillas, Excepciones, Roles y Objetos de Ricardo Devis Designing Components with the C++ STL de Ulrich Breymann Effective STL de Scott Meyers Por ahora veamos un ejemplo de STL donde hemos utilizado una plantilla de Lista: Guias de Estudio Lenguaje Orientado a Objetos, desarrolladas por: Adrin Izquierdo, docente ITP

#include <iostream> #include <list> using namespace std; // funcion auxiliar void mostrarListaEntera(const list<int> & L) { //Declaracion de un iterador de enteros list<int>::const_iterator I = L.begin(); while(I != L.end()) cout << *I++ << ' '; cout << " tamao() =" << L.size() << endl; } int main() { // define dos listas de enteros <int> list<int> Lista1, Lista2; //aade tres nmeros a la Lista1 (Lista1).push_back(1); (Lista1).push_back(2); (Lista1).push_back(3); //aade tres nmeros a la Lista2 (Lista2).push_back(9); (Lista2).push_back(8); (Lista2).push_back(7); //Muestra la Lista1 y su tamao mostrarListaEntera(Lista1); //Muestra la Lista2 y su tamao mostrarListaEntera(Lista2); //Une las listas con merge es decir el contenido queda en la primera //y la segunda vacia Lista1.merge(Lista2); //Muestra la Lista1 ya unida a la Lista2 su tamao mostrarListaEntera(Lista1); //Muestra la Lista2 que esta vacia y su tamao mostrarListaEntera(Lista2); return 0; }

Guias de Estudio Lenguaje Orientado a Objetos, desarrolladas por: Adrin Izquierdo, docente ITP

El programa genera los siguiente resultados: 1 2 3 tamao() =3 9 8 7 tamao() =3 1 2 3 9 8 7 tamao() =6 tamao() =0 MANEJO DE ARCHIVOS EN C++ El curso de Programacin Orientada a Objetos se considera terminado, pero para realizar la prctica final es necesario que se conozcan el manejo de archivos en C o en C++, para ello se solicita investigar acerca de este tema. La practica se puede realizar de las dos maneras, leyendo los archivos de la forma que lo hace C, por medio de funciones como fopen fclose fgets feof sscanf, etc. Aqu dejo un ejemplo de una funcion que lee un archivo linea por linea: int f_leerLinea( FILE *ftxt, char * linea ) { int error = 0; char c = ' '; do { if (fgets(linea, 90, ftxt)== NULL) { error = ERROR_LECTURA; } else { c = linea[0]; }; } while ( (!feof(ftxt)) && (!error) && ( (c=='.') || (c==' ') || (c=='\r') || (c=='\n') ) ); return (error); } /* f_leerLinea */ O tambin a la manera de C++, para esto, una lectura interesante son los captulos 8 y 9 del libro (del que me he basado en gran parte este material) titulado C++ Gua de Autoenseanza de Hebert Schildt. Capitulo 8: Introduccin al sistema de E/S de C++ Capitulo 9: E/S Avanzada en C++

Guias de Estudio Lenguaje Orientado a Objetos, desarrolladas por: Adrin Izquierdo, docente ITP

PRACTICA FINAL
Enunciado Desarrollo de una aplicacin que gestiona informacin relativa a la gestin de vuelos. En primer lugar, se dispone de una relacin de aeropuertos. De cada aeropuerto (podemos suponer que como mximo nos interesan 20) dispondremos de la siguiente informacin: - Cdigo del aeropuerto: Se utiliza en los vuelos para identificar el aeropuerto de llegada y de salida. - Nombre del aeropuerto - Poblacin - Pas - Diferencia Horaria GMT: Para poder determinar la hora local de un lugar, es necesario conocer en que huso horario se encuentra . Se toma como referencia la hora del meridiano de Greenwich (GMT), a partir de la cual se puede calcular la diferencia horaria entre dos puntos. Tambin se dispone informacin sobre los vuelos relacionados con dichos aeropuertos. Los vuelos se clasifican en regulares y charter. En todos los casos, de cada vuelo se conoce: - Tipo de Vuelo (R/C , que corresponden a Regular o Charter) - Aeropuerto Origen - Aeropuerto Destino - Duracin del vuelo. Su formato es 00:00 (horas y minutos) - Compaia - Tipo Avion - Numero de plazas En el caso de vuelos regulares, se conoce adicionalmente su regularidad: - Frecuencia de vuelo: Indicando el formato DiaSemana-HoraSalida DiaSemana-HoraSalida DiaSemana corresponde a un valor entre L,M,X,J,V,S,D HoraSalida tiene el formato 00:00 (horas y minutos) Se utiliza un - (guin) como separador entre DiaSemana y HoraSalida. Se utiliza un (espacio) como separador entre las diferentes salidas. En el caso de vuelos charter, la informacin adicional que se conoce es: - Agencia contratante - Da y Hora Salida. Su formato es aaaa/mm/dd hh:mm (Ejemplo: 2009/02/15 20:30) En un futuro se prev aadir otros tipos de vuelos, por lo que el cdigo fuente debe permitir aadir un nuevo tipo de vuelos realizando los mnimos cambios en el cdigo fuente. Toda la informacin relativa a aeropuertos y vuelos se deber introducir mediante un fichero texto (vuelos.txt) que tendr el siguiente formato: Para los aeropuertos: Cod ; Nombre del aeropuerto ; Poblacin ; Pas ; Diferencia Horaria GMT Para los vuelos: - Si son regulares R; Origen; Destino; Duracin ; Compaa; Tipo Avin; Plazas; Frecuencia - Si son vuelos charter: C; Origen; Destino; Duracin ; Compaa; Tipo Avin; Plazas; Agencia; Dia-Hora Salida Ejemplo vuelos.txt #Aeropuertos BCN01;Barcelona - El Prat;Barcelona;Espaa;1 MAD01;Madrid - Barajas;Madrid;Espaa;1 PAR01;Paris Orly;Paris;Francia;1 Guias de Estudio Lenguaje Orientado a Objetos, desarrolladas por: Adrin Izquierdo, docente ITP

LON01;London - Heathrow;Londres;Gran Bretaa;0 SPA01;Sao Paulo - Guarulhos;Sao Paulo;Brasil;-3 #Vuelos R;BCN01;MAD01;01:00;Iberia;Airbus;150;L-15:00 X-15:00 V-15:00 D-15:00 R;MAD01;BCN01;01:00;Iberia;Airbus;150;L-18:00 J-20:00 S-20:00 R;BCN01;LON01;01:05;British Air;Boeing;180;L-10:00 J-10:00 R;LON01;BCN01;01:05;British Air;Boeing;180;L-15:00 J-15:00 R;BCN01;LON01;01:10;Ryan Air;Airbus;120;L-10:00 J-10:00 R;LON01;BCN01;01:10;Ryan Air;Airbus;120;J-15:10 J-15:10 R;LON01;SPA01;07:00;British Air;Boeing;200;X-09:45 J-09:45 S-09:45 R;SPA01;MAD01;07:00;British Air;Boeing;200;X-20:25 J-20:25 S-20:25 C;BCN01;MAD01;01:00;Spanair;Airbus;150;Viajes Condor;2009/01/15 20:30 C;MAD01;BCN01;01:00;Iberia;Airbus;150;Viajes Condor;2009/01/22 20:30 C;BCN01;LON01;01:00;British Air;Boeing;180;Viaje Ilusion;2009/02/22 20:30 C;LON01;BCN01;01:00;British Air;Boeing;180;Viaje Ilusion;2009/03/05 15:19 C;BCN01;LON01;01:00;Ryan Air;Airbus;120;TravelPlan;2009/01/25 15:18 C;LON01;BCN01;01:00;Ryan Air;Airbus;120;TravelPlan;2009/01/31 22:20 ... El proceso a realizar es: 1. Leer los datos (vuelos.txt) Se leen los datos del fichero vuelos.txt y se carga la informacin en memoria de forma organizada. Al final, de la lectura debe mostrar un mensaje final que resuma la operacin: Aeropuertos ledos : xxx Total Vuelos ledos : xxx 2. Generar los siguientes listados a) Listado de aeropuertos (aeropuertos.txt) Se muestra los datos generales de los aeropuertos (Ejemplo:) Cod Aeropuerto Poblacin Pas Dif.GMT -------------------------------------------------------------------------------------------------BCN01 El Prat de Llobregat Barcelona Espaa 1 MAD01 Barajas Madrid Espaa 1 PAR01 Paris Orly Paris Francia 1 LON01 Heathrow London Londres Gran Bretaa 0 SPA01 Sao Paulo - Guarulhos Sao Paulo Brasil -3 -------------------------------------------------------------------------------------------------5 aeropuertos b) Listado de vuelos (solo para enero de 2009). i. Para cada aeropuerto de la lista, generar un fichero con: 1. los vuelos de salida de dicho aeropuerto 2. los vuelos de llegada a dicho aeropuerto Cada listado deber salir ordenado por fecha y hora. El fichero recibir el nombre del aeropuerto (BCN01.txt). El resultado ser de la forma (cuidado: el ejemplo no utiliza datos generados realmente) AEROPUERTO: BCN01 El Prat de Llobregat ENERO 2009 SALIDAS: Dest Salida (h.local) Llegada (h.local) Compaia Plazas Otros Datos ------------------------------------------------------------------------------------------------------------MAD01 02/01 15:00 02/01 16:00 Iberia 150 R, prox:04/01 15:00 Guias de Estudio Lenguaje Orientado a Objetos, desarrolladas por: Adrin Izquierdo, docente ITP

... ------------------------------------------------------------------------------------------------------------10 vuelos 1527 plazas mximo LLEGADAS: Orig Llegada (h.local) Salida (h.local) Compaia Plazas Otros Datos ------------------------------------------------------------------------------------------------------------MAD01 02/01 16:00 02/01 15:00 Iberia 150 R, prox:04/01 16:00 ... ------------------------------------------------------------------------------------------------------------12 vuelos 1250 plazas mximo Las columnas Llegada y Salida (hora local) se obtiene a partir de la informacin de la hora de salida, duracin del vuelo y diferencia horaria. La columna Otros Datos depender del tipo de vuelo, a) si el vuelo es Regular muestra R, frecuencia horaria de salida. b) si el vuelo es Charter muestra C, agencia contratante: En este punto, el consejo es generar una estructura de datos adicional con todos los vuelos (regulares, a partir del patrn establecido, y charter) con sus respectivas horas de salida y llegada calculadas, y ordenada segn el criterio establecido. Esta estructura solo deber generarse para el intervalo de fechas solicitado (Enero 2009). Observaciones: Aunque para el desarrollo de la aplicacin sera ms conveniente utilizar memoria dinmica, para que sea ms fcil y rpido se permite (y aconseja) la implementacin de las diferentes estructuras de datos en memoria esttica (vectores). Tambin para simplificar se puede considerar que las entradas de datos son correctas. Desarrollar la aplicacin en un lenguaje orientado a objetos (C++ / Java ) En este apartado se valorar principalmente la estructura de clases creada (cada clase en un fichero separado, y con su archivo de cabecera), y la aplicacin de los conceptos de orientacin a objetos en C++ (encapsulacin, herencia, polimorfismo,...). En concreto, SE DEBE aplicar herencia para los vuelos y polimorfismo en el listado 2b. El lenguaje preferentemente C++ donde se exige que se utilice como si fuera un lenguaje orientado a objetos puro (es decir, no existen variables ni funciones fuera de las clases definidas). Los ficheros solucin se entregarn compactados, adems de un fichero leeme.txt explicando el entorno utilizado y las posibles incidencias, en un nico archivo llamado ExamenOO.zip

Guias de Estudio Lenguaje Orientado a Objetos, desarrolladas por: Adrin Izquierdo, docente ITP

Potrebbero piacerti anche