Programación en Ingeniería Electrónica Escuela Técnica Superior de Ingenieros de Telecomunicaciones Universidad de Las Palmas de Gran Canaria Programación Básica en C++ 2008 (c) Luis Hernández Programación en Ingeniería Electrónica | Programación Básica en C++ 1 0. Contenido Introducción Diferencias entre C y C++ Creación de Clases y Objetos Primer Programa Entrada/Salida por Consola en C++ Constructores y Destructores Funciones Automáticas Utilizar Estructuras como Clases Operaciones con Objetos 2008 (c) Luis Hernández Programación en Ingeniería Electrónica | Programación Básica en C++ 2 0. Contenido Funciones Amigas This, New y Delete Referencias Herencia Funciones Virtuales Sobrecarga Ficheros Excepciones 2008 (c) Luis Hernández Programación en Ingeniería Electrónica | Programación Básica en C++ 3 1. Introducción Los programas se basan en estructuras de control bien definidas, bloques de código, subrutinas independientes que soportan recursividad y variables locales. La esencia de la programación estructurada es la reducción de un programa a sus elementos constituidos. 2008 (c) Luis Hernández Programación en Ingeniería Electrónica | Programación Básica en C++ 4 1. Introducción La programación orientada a objetos (POO), permite descomponer un problema en subgrupos relacionados. Cada subgrupo pasa a ser un objeto autocontenido que contiene sus propias instrucciones y datos que le relacionan con ese objeto. Todos los lenguajes POO comparten tres características: encapsulación, polimorfismo y herencia. 2008 (c) Luis Hernández Programación en Ingeniería Electrónica | Programación Básica en C++ 5 1.1. Encapsulación Es el mecanismo que agrupa el código y los datos que maneja. Los mantiene protegidos frente a cualquier interferencia y mal uso. Cuando el código y los datos están enlazados de esta manera se ha creado un objeto. Ese código y datos pueden ser privados para ese objeto o públicos para otras partes del programa. 2008 (c) Luis Hernández Programación en Ingeniería Electrónica | Programación Básica en C++ 6 1.2. Polimorfismo Es la cualidad que permite que un nombre se utilice para dos o más propósitos relacionados pero técnicamente diferentes. El propósito es poder usar un nombre para especificar una clase general de acciones. Por ejemplo, en C tenemos tres funciones distintas para devolver el valor absoluto. Sin embargo, C++ incorpora polimorfismo y a cada una de las funciones se le puede llamar abs(). El polimorfismo se puede aplicar tanto a funciones como a operadores. 2008 (c) Luis Hernández Programación en Ingeniería Electrónica | Programación Básica en C++ 7 1.3. Herencia Proceso mediante el cual un objeto puede adquirir las propiedades de otro objeto. La información se hace manejable utilizando una organización jerárquica. 2008 (c) Luis Hernández Programación en Ingeniería Electrónica | Programación Básica en C++ 8 1.4. Objeto Conjunto de variables y funciones encapsulados pertenecientes a una clase. A este encapsulamiento se le denomina objeto. Por tanto, la clase es quien define las características y funcionamiento del objeto. 2008 (c) Luis Hernández Programación en Ingeniería Electrónica | Programación Básica en C++ 9 2. Diferencias entre C y C++ En C, cuando una función no toma parámetros, su prototipo tiene la palabra void; sin embargo en C++ no es necesario En un programa de C++ todas las funciones deben estar en forma de prototipo, en C los prototipos son opcionales. Si una función de C++ es declarada para devolver un valor, obligatoriamente debe devolverse un valor; en C no es necesario. En C, las variables solo pueden declaradarse al principio del bloque, mientras que en C++ se pueden declarar en cualquier punto. 2008 (c) Luis Hernández Programación en Ingeniería Electrónica | Programación Básica en C++ 10 3. Creación de Clases y Objetos La base del encapsulamiento es la clase, a partir de ellas se le dan las características y comportamiento a los objetos. Lo primero es crear la clase y después, en la función main (que sigue siendo la principal), crearemos los objetos de cada una de las clases. Las variables y funciones de una clase pueden ser publicas, privadas o protegidas. Por defecto, si no se indica nada, son privadas. Estos modificadores nos indican en que partes de un programa podemos utilizar las funciones y variables. 2008 (c) Luis Hernández Programación en Ingeniería Electrónica | Programación Básica en C++ 11 3. Creación de Clases y Objetos private: Solo tendrán acceso los de la misma clase donde estén definidos. public: Se pude hacer referencia desde cualquier parte del programa. protected: Se puede hacer referencia desde la misma clase y las subclases. 2008 (c) Luis Hernández Programación en Ingeniería Electrónica | Programación Básica en C++ 12 3.1. Ejemplo class miclase{ int a; public: void funcion1(int num); int funcion2(); } 2008 (c) Luis Hernández Programación en Ingeniería Electrónica | Programación Básica en C++ 13 4. Primer Programa class miclase{ int a; public: void pasar_a(int num); int mostrar_a(); }; void miclase::pasar_a(int num){ a=num; } int miclase::mostrar_a(){ return a; } 2008 (c) Luis Hernández Programación en Ingeniería Electrónica | Programación Básica en C++ 14 4. Primer Programa void main(){ miclase obj1, obj2; clrscr(); obj1.pasar_a(10); obj2.pasar_a(99); printf("%d\n",obj1.mostrar_a()); printf("%d\n",obj2.mostrar_a()); getch(); } 2008 (c) Luis Hernández Programación en Ingeniería Electrónica | Programación Básica en C++ 15 5. Entrada/Salida por Consola en C++ En C++ se pueden seguir utilizando las mismas sentencias para mostrar información por pantalla o pedirla desde teclado. Pero ahora se añaden dos nuevas, de la misma potencia y mayor facilidad de uso: Mostrar por pantalla: cout << expresión y pedir por teclado: cin >> variable La cabecera que utilizan estas dos sentencias es iostream.h. La variable pude ser de cualquier tipo. 2008 (c) Luis Hernández Programación en Ingeniería Electrónica | Programación Básica en C++ 16 5.1. Ejemplo void main(){ int i,j; double d; clrscr(); i=10; j=15; cout <<"Introducir valor: "; cin>>d; cout << "Estos son los valores: "; cout << i << " "<< j << " "<< d; getch(); } 2008 (c) Luis Hernández Programación en Ingeniería Electrónica | Programación Básica en C++ 17 6. Constructores y Destructores Técnicamente un constructor y un destructor son funciones que se utilizan para inicializar y destruir los objetos. También se pueden utilizar para realizar cualquier otra operación. Sin embargo esto se considera un estilo de programación pobre. 2008 (c) Luis Hernández Programación en Ingeniería Electrónica | Programación Básica en C++ 18 6.1. Constructores En los programas hay partes que requieren inicialización. Esta necesidad de inicialización es incluso más común cuando se está trabajando con objetos. Para tratar esta situación, C++ permite incluir una función constructora. A estas funciones se las llama automáticamente cada vez que se crea un objeto de esa clase. La función constructora debe tener el mismo nombre que la clase de la que es parte, no tienen tipo devuelto pero si es posible pasarle valores a modo de parámetros. 2008 (c) Luis Hernández Programación en Ingeniería Electrónica | Programación Básica en C++ 19 6.1.1. Ejemplo class miclase{ int a; public: miclase(); void show(); }; miclase::miclase() { a=100; } 2008 (c) Luis Hernández Programación en Ingeniería Electrónica | Programación Básica en C++ 20 6.1.1. Ejemplo void miclase::show(){ cout << a; } void main(){ clrscr(); miclase obj; obj.show(); getch(); } 2008 (c) Luis Hernández Programación en Ingeniería Electrónica | Programación Básica en C++ 21 6.2. Destructores El complemento de un constructor es la función destructora. A esta función se la llama automáticamente cuando se destruye el objeto. El nombre de las funciones destructoras debe ser el mismo que el de la clase a la que pertenece precedido del carácter ~. Los objetos se destruyen cuando se sale de ámbito si son locales y al salir del programa si son globales. Las funciones destructoras no devuelve tipo alguno y tampoco pueden recibir parámetros. 2008 (c) Luis Hernández Programación en Ingeniería Electrónica | Programación Básica en C++ 22 6.2.1. Ejemplo class miclase{ int a; public: miclase(); ~miclase(); void show(); }; miclase::miclase(){ a=100; } 2008 (c) Luis Hernández Programación en Ingeniería Electrónica | Programación Básica en C++ 23 6.2.1. Ejemplo miclase::~miclase() { cout << "Destruyendo...\n"; getch(); } void miclase::show(){ cout << a; } void main(){ clrscr(); miclase obj; obj.show(); getch(); } 2008 (c) Luis Hernández Programación en Ingeniería Electrónica | Programación Básica en C++ 24 6.3. Contructores con parámetros Es posible pasar argumentos a una función constructora. Para permitir esto, simplemente añada los parámetros a la declaración y definición de la función constructora. Después, cuando declare un objeto, especifique los parámetros como argumentos. 2008 (c) Luis Hernández Programación en Ingeniería Electrónica | Programación Básica en C++ 25 6.3.1. Ejemplo class miclase{ int a; public: miclase(int x); void mostrar(); }; miclase::miclase(int x){ cout << "Constructor"; a=x; } 2008 (c) Luis Hernández Programación en Ingeniería Electrónica | Programación Básica en C++ 26 6.3.1. Ejemplo void miclase::miclase() { cout <<"El valor de a es: "; cout << a; } void main(){ miclase objeto(4); ob.show(); getch(); } 2008 (c) Luis Hernández Programación en Ingeniería Electrónica | Programación Básica en C++ 27 7. Funciones Automáticas La característica principal de las funciones automáticas es que su definición es lo suficientemente corta para incluirse dentro de la declaración de la clase. Las restricciones son: no puede contener variables de tipo static, una sentencia de bucle, o un switch. El uso más común de las funciones automáticas es en las funciones constructoras. 2008 (c) Luis Hernández Programación en Ingeniería Electrónica | Programación Básica en C++ 28 7.1. Ejemplo class ejemplo{ public: int valor(int x) { return !(X%2);} }; void main(){ int a; cout <<"Introducir valor: "; cin >> a; if (valor(a)) cout << "Es par "; else cout << "Es impar"; } 2008 (c) Luis Hernández Programación en Ingeniería Electrónica | Programación Básica en C++ 29 8. Utilizar Estructuras como Clases En C++, la definición de una estructura se ha ampliado para que pueda también incluir funciones miembro, incluyendo funciones constructoras y destructoras como una clase. De hecho, la única diferencia entre una estructura y una clase es que, por omisión, los miembros de una clase son privados y los miembros de una estructura son públicos. 2008 (c) Luis Hernández Programación en Ingeniería Electrónica | Programación Básica en C++ 30 8.1. Ejemplo struct tipo{ tipo(double b, char *n); void mostrar(); private: double balance; char nombre[40]; }; tipo::tipo(double b, char *n){ balance=b; strcpy(nombre,n); } 2008 (c) Luis Hernández Programación en Ingeniería Electrónica | Programación Básica en C++ 31 8.1. Ejemplo void tipo::mostrar(){ cout << "Nombre: " << nombre; cout << ": $" << balance; if (balance<0.0) cout << "****"; cout << "\n"; } void main(){ tipo acc1(100.12, "Ricardo"); tipo acc2(-12.34, "Antonio"); acc1.mostrar(); acc2.mostrar(); getch(); } 2008 (c) Luis Hernández Programación en Ingeniería Electrónica | Programación Básica en C++ 32 9. Operaciones con Objetos Asignación de Objetos Array de Objetos Paso de Objetos a Funciones Objetos devueltos por Funciones Punteros a Objetos 2008 (c) Luis Hernández Programación en Ingeniería Electrónica | Programación Básica en C++ 33 9.1. Asignación de Objetos Se puede asignar un objeto a otro a condición de que ambos objetos sean del mismo tipo (misma clase). Cuando un objeto se asigna a otro se hace una copia a nivel de bits de todos los miembros, es decir, se copia el contenido de todos los datos. Despues de la copia, los objetos continúan siendo independientes. 2008 (c) Luis Hernández Programación en Ingeniería Electrónica | Programación Básica en C++ 34 9.1.1. Ejemplo class miclase{ int a,b; public: void obtener(int i, int j){a=i;b=j;} void mostrar(){cout << a << " "<< b << "\n";} }; void main(){ miclase o1,o2; o1.obtener(10, 4); o2=o1; o1.show(); o2.show(); getch(); } 2008 (c) Luis Hernández Programación en Ingeniería Electrónica | Programación Básica en C++ 35 9.2. Array de Objetos Los objetos son variables y tienen las mismas cualidades y atributos que cualquier tipo de variables, por tanto es posible disponer objetos en un array. La sintaxis es exactamente igual a la utilizada para declarar y acceder al array. También disponemos de arrays bidimensionales. 2008 (c) Luis Hernández Programación en Ingeniería Electrónica | Programación Básica en C++ 36 9.2.1. Ejemplo class ejemplo{ int a; public: void pasar(int x){a=x;} int mostrar() {return a;} }; 2008 (c) Luis Hernández Programación en Ingeniería Electrónica | Programación Básica en C++ 37 9.2.1. Ejemplo void main() { ejemplo ob[4]; int indice; clrscr(); for(indice=0;indice<4;indice++) ob[indice].pasar(indice); for(indice=0;indice<4;indice++) { cout << ob[indice].mostrar(); cout << "\n"; } getch(); } 2008 (c) Luis Hernández Programación en Ingeniería Electrónica | Programación Básica en C++ 38 9.3. Paso de Objetos a Funciones Los objetos se pueden pasar a funciones como argumentos de la misma manera que se pasan otros tipos de datos. Hay que declarar el parámetro como un tipo de la clase y después usar un objeto de esa clase como argumento cuando se llama a la función. Cuando se crea una copia de un objeto porque se usa como argumento para una función, no se llama a la función constructora. Sin embargo, cuando la copia se destruye (al salir de ámbito), se llama a la función destructora. 2008 (c) Luis Hernández Programación en Ingeniería Electrónica | Programación Básica en C++ 39 9.3.1. Ejemplo class objeto{ int i; public: objeto(int n){i=n;} int devol(){return i;} }; int sqr(objeto o){ return o.devol()*o.devol(); } void main(){ objeto a(10), b(2); cout << sqr(a); cout << sqr(b); getch(); } 2008 (c) Luis Hernández Programación en Ingeniería Electrónica | Programación Básica en C++ 40 9.4. Objetos devueltos por Funciones Al igual que se pueden pasar objetos, las funciones pueden devolver objetos. Primero hay que declarar la función para que devuelva un tipo de la clase. Segundo hay que devolver un objeto de ese tipo usando la sentencia return. Cuando un objeto es devuelto por una función, se crea automáticamente un objeto temporal que guarda el valor devuelto. Este es el objeto que realmente devuelve la función. Después el objeto se destruye, esto puede causar efectos colaterales inesperados. 2008 (c) Luis Hernández Programación en Ingeniería Electrónica | Programación Básica en C++ 41 9.4.1. Ejemplo class ejemplo{ char cadena[80]; public: void muestra(){cout<<cadena<<"\n";} void copia(char *cad){strcpy(cadena,cad);} }; 2008 (c) Luis Hernández Programación en Ingeniería Electrónica | Programación Básica en C++ 42 9.4.1. Ejemplo ejemplo entrada(){ char cadena[80]; ejemplo str; cout<<"Introducir cadena: "; cin>>cadena; str.copia(cadena); return str; } void main(){ ejemplo ob; ob=entrada(); ob.muestra(); getch(); } 2008 (c) Luis Hernández Programación en Ingeniería Electrónica | Programación Básica en C++ 43 9.5. Punteros a Objetos Hasta ahora se ha accedido a miembros de un objeto usando el operador punto (.). Es posible acceder a un miembro de un objeto a través de un puntero a ese objeto. Cuando sea este el caso, se emplea el operador de flecha (->) en vez del operador punto. Para obtener la dirección de un objeto, se precede al objeto con el operador &. Se trabaja de igual forma que los punteros a otros tipos. 2008 (c) Luis Hernández Programación en Ingeniería Electrónica | Programación Básica en C++ 44 9.5.1. Ejemplo class miclase{ int a; public: miclase(int x); int get(); }; miclase::miclase(int x){ a=x; } int miclase::get(){ return a; } 2008 (c) Luis Hernández Programación en Ingeniería Electrónica | Programación Básica en C++ 45 9.5.1. Ejemplo void main(){ clrscr(); miclase obj(200); miclase *p; p=&obj; cout << "Valor del Objeto es " << obj.get(); cout << "Valor del Puntero es " << p->get(); getch(); } 2008 (c) Luis Hernández Programación en Ingeniería Electrónica | Programación Básica en C++ 46 10. Funciones Amigas Puede ser necesario que una función acceda a los miembros privados de una clase sin que la función sea realmente un miembro de la clase. Las funciones amigas son útiles para la sobrecarga de operadores y la creación de ciertos tipos de funciones E/S. El prototipo de estas funciones viene precedido por la palabra clave friend, pero al desarrollarla no es necesario incluirla. Una función amiga no se puede calificar mediante un nombre de objeto (no es miembro). Estas funciones no se heredan y pueden ser amigas de más de una clase. 2008 (c) Luis Hernández Programación en Ingeniería Electrónica | Programación Básica en C++ 47 10.1. Ejemplo class miclase{ int n,d; public: miclase(int i, int j){n=i;d=j;} friend int factor(miclase ob); }; int factor(miclase ob){ if (!(ob.n%ob.d)) return 1; else return 0; } 2008 (c) Luis Hernández Programación en Ingeniería Electrónica | Programación Básica en C++ 48 10.1. Ejemplo void main(){ miclase obj1(10, 2), obj2(3, 2); if(factor(obj1)) cout << "es factor"; else cout << "no es factor"; getch(); } 2008 (c) Luis Hernández Programación en Ingeniería Electrónica | Programación Básica en C++ 49 11. This, New y Delete This New y Delete 2008 (c) Luis Hernández Programación en Ingeniería Electrónica | Programación Básica en C++ 50 11.1. This This es un puntero que se pasa automáticamente a cualquier miembro cuando se invoca. Es un puntero al objeto que genera la llamada, por tanto, la función recibe automáticamente un puntero al objeto. Recalcar que este puntero solo se pasa a los miembros apuntados por this. 2008 (c) Luis Hernández Programación en Ingeniería Electrónica | Programación Básica en C++ 51 11.1.1. Ejemplo class stock{ char item[20]; double coste; public: stock(char *i,double c){ strcpy(item,i); coste=c; } void muestra(); }; 2008 (c) Luis Hernández Programación en Ingeniería Electrónica | Programación Básica en C++ 52 11.1.1. Ejemplo void stock::muestra(){ cout<<item << "\n"; cout<<"PVP: " << coste; } void main(){ clrscr(); stock obj("tuerca",5.94); obj.muestra(); getch(); } 2008 (c) Luis Hernández Programación en Ingeniería Electrónica | Programación Básica en C++ 53 11.1.2. Ejemplo class stock{ char item[20]; double coste; public: stock(char *i,double c) { strcpy(this->item,i); this->coste=c; } void muestra(); }; 2008 (c) Luis Hernández Programación en Ingeniería Electrónica | Programación Básica en C++ 54 11.1.2. Ejemplo void stock::muestra(){ cout<<this->item << "\n"; cout<<"PVP: " << this->coste; } void main(){ clrscr(); stock obj("tuerca",5.94); obj.muestra(); getch(); } 2008 (c) Luis Hernández Programación en Ingeniería Electrónica | Programación Básica en C++ 55 11.2. New y Delete Hasta ahora si se necesitaba asignar memoria dinámica, se hacía con malloc y para liberarla se utilizaba free. En C++ se puede asignar memoria utilizando new y liberarse mediante delete. Estas operadores no se pueden combinar unas con otras, es decir, debe llamarse a delete solo con un puntero obtenido mediante new. A los objetos también se les puede pasar un valor inicial con la sentencia new. También se pueden crear arrays asignados dinámicamente, es decir, pueden utilizar la sentencia new. 2008 (c) Luis Hernández Programación en Ingeniería Electrónica | Programación Básica en C++ 56 11.2.1. Ejemplo class cosas{ int i,j; public: void obten(int a,int b){i=a;j=b;} int muestra(){return i*j;} }; 2008 (c) Luis Hernández Programación en Ingeniería Electrónica | Programación Básica en C++ 57 11.2.1. Ejemplo void main(){ int *p_var; p_var=new int; // p_var=new int(9); cosas *p; p=new cosas; if(!p || !p_var) { cout<<"Error de asignacion\n"; exit(1); } *p_var=1000; p->obten(4,5); cout<<"El entero en p_var es: " <<*p_var; cout<<"\nTotal: " <<p->muestra(); getch(); } 2008 (c) Luis Hernández Programación en Ingeniería Electrónica | Programación Básica en C++ 58 11.2.2. Ejemplo void main(void){ int *p; int i; p=new int[5]; if(!p){ cout<<"Error de asignacion\n"; exit(1); } for(i=0;i<5;i++) p[i]=i+1; for(i=0;i<5;i++) { cout<<"Este es el entero en p["<<i<<"]:"; cout<<p[i]<<"\n"; } delete[] p; getch(); } 2008 (c) Luis Hernández Programación en Ingeniería Electrónica | Programación Básica en C++ 59 12. Referencias C++ consta de una particularidad relacionada con los punteros, la denominada referencia. Una referencia es un puntero implícito que se comporta como una variable normal. Existen varios modos de utilizar una referencia: se puede pasar a una función, ser devuelta por una función y crearse como una referencia independiente (casi nunca se utilizan). Lo apuntado por una referencia no puede ser modificado. 2008 (c) Luis Hernández Programación en Ingeniería Electrónica | Programación Básica en C++ 60 12. Referencias En el caso de las referencias devueltas por una función se puede poner el nombre de la función en el lado izquierdo de la expresión. Es como asignar un valor a una variable. Hay que tener en cuenta el ámbito de la variable que se comporta como una referencia. 2008 (c) Luis Hernández Programación en Ingeniería Electrónica | Programación Básica en C++ 61 12.1. Ejemplo void f(int *n); void main() { int i=0; f(&i); cout<<"valor i:" << i; getch(); } void f(int *n) { *n=100; } 2008 (c) Luis Hernández Programación en Ingeniería Electrónica | Programación Básica en C++ 62 12.2. Ejemplo void f(int &n); void main() { int i=0; f(i); cout<<"valor i:"<< i; getch(); } void f(int &n) { n=100; } 2008 (c) Luis Hernández Programación en Ingeniería Electrónica | Programación Básica en C++ 63 12.3. Ejemplo int &f(); int x; void main() { clrscr(); f()=100; cout<<"Valor de x: " <<x; getch(); } int &f() { return x; } 2008 (c) Luis Hernández Programación en Ingeniería Electrónica | Programación Básica en C++ 64 13. Herencia Clase Base y Clase Derivda Tipos de acceso Herencia múltiple 2008 (c) Luis Hernández Programación en Ingeniería Electrónica | Programación Básica en C++ 65 13.1. Clase Base y Clase Derivada Cuando una clase hereda de otra, la clase que se hereda se llama clase base y la clase que hereda se llama clase derivada. La clase base define todas las cualidades que serán comunes a cualquier clase derivada. El acceso a la clase base puede ser: public, private y protected. 2008 (c) Luis Hernández Programación en Ingeniería Electrónica | Programación Básica en C++ 66 13.2. Tipos de acceso Si el acceso es public, todos los atributos de la clase base son públicos para la derivada, el resto con acceso. Si el acceso es private, los datos son privados para la clase base y la derivada no tiene acceso, el resto sin acceso. Si el acceso es protected, los datos son privados para la base y la derivada tiene acceso, el resto sin acceso. 2008 (c) Luis Hernández Programación en Ingeniería Electrónica | Programación Básica en C++ 67 13.2.1. Ejemplo class miclase{ int a; protected: int b; public: int c; miclase(int n,int m){a=n;b=m;} int obten_a(){return a;} int obten_b(){return b;} }; 2008 (c) Luis Hernández Programación en Ingeniería Electrónica | Programación Básica en C++ 68 13.2.1. Ejemplo void main() { miclase objeto(10, 20); clrscr(); objeto.c=30; // objeto.b=30; error, sin acceso. // objeto.a=30; error, sin acceso. cout<<objeto.obten_a() <<"\n"; cout<<objeto.obten_b() <<"\n"; cout<<objeto.c; getch(); } 2008 (c) Luis Hernández Programación en Ingeniería Electrónica | Programación Básica en C++ 69 13.2.2. Ejemplo class base{ int x; public: void get_x(int a){x=a;} void show_x(){cout<< x;} }; class derivada:public base{ int y; public: void get_y(int b){y=b;} void show_y(){cout<<y;} }; 2008 (c) Luis Hernández Programación en Ingeniería Electrónica | Programación Básica en C++ 70 13.2.2. Ejemplo void main() { derivada obj; clrscr(); obj.get_x(10); obj.get_y(20); obj.show_x(); cout<<"\n"; obj.show_y(); getch(); } 2008 (c) Luis Hernández Programación en Ingeniería Electrónica | Programación Básica en C++ 71 13.2.3. Ejemplo class base{ int x; public: void get_x(int a){x=a;} void show_x(){cout<<x <<"\n";} }; class derivada:private base{ int y; public: void get_xy(int a,int b){get_x(a);y=b;} void show_xy(){show_x();cout<<y<<"\n";} }; 2008 (c) Luis Hernández Programación en Ingeniería Electrónica | Programación Básica en C++ 72 13.2.3. Ejemplo void main() { clrscr(); derivada ob; ob.get_xy(10, 20); ob.show_xy(); // ob.get_x(10); error, sin acceso // ob.show_x(); error, sin acceso getch(); } 2008 (c) Luis Hernández Programación en Ingeniería Electrónica | Programación Básica en C++ 73 13.3. Herencia Múltiple Existen dos casos en los que una clase derivada puede heredar de más una clase base (herencia múltiple). El primero, una clase derivada es usada como la clase base de otra clase derivada, creándose una jerarquía de clases. El segundo, una clase derivada puede heredar directamente de más de una clase base. En esta situación se combinan dos o más clases base para facilitar la creación de la clase derivada. 2008 (c) Luis Hernández Programación en Ingeniería Electrónica | Programación Básica en C++ 74 13.3. Herencia Múltiple Los constructores se ejecutan en orden descendente, es decir primero se llama al constructor de la clase base y luego al de las derivadas. En las destructoras ocurre en orden inverso, primero el de las derivadas y luego el de la base. 2008 (c) Luis Hernández Programación en Ingeniería Electrónica | Programación Básica en C++ 75 13.3.1. Ejemplo class base_a{ int a; public: base_a(int x){a=x;} int ver_a(){return a;} }; class deriva_b:public base_a{ int b; public: deriva_b(int x, int y):base_a(x){b=y;} int ver_b(){return b;} }; 2008 (c) Luis Hernández Programación en Ingeniería Electrónica | Programación Básica en C++ 76 13.3.1. Ejemplo class deriva_c:public deriva_b{ int c; public: deriva_c(int x,int y,int z):deriva_b(x,y){c=z;} void ver_todo() { cout<<ver_a()<<" "<<ver_b()<<" "<<c; } }; void main() { deriva_c ob(1, 2, 3); ob.ver_todo(); cout<<"\n"; cout<<ob.ver_a()<<" "<<ob.ver_b(); getch(); } 2008 (c) Luis Hernández Programación en Ingeniería Electrónica | Programación Básica en C++ 77 13.3.2. Ejemplo class B1{ int a; public: B1(int x){a=x;} int obten_a(){return a;} }; class B2{ int b; public: B2(int x){b=x;} int obten_b(){return b;} }; 2008 (c) Luis Hernández Programación en Ingeniería Electrónica | Programación Básica en C++ 78 13.3.2. Ejemplo class C1:public B1,public B2{ int c; public: C1(int x,int y,int z):B1(z),B2(y) { c=x; } void muestra() { cout<<obten_a()<<" "<<obten_b()<<" "; cout<<c<<"\n"; } }; 2008 (c) Luis Hernández Programación en Ingeniería Electrónica | Programación Básica en C++ 79 13.3.2. Ejemplo void main() { clrscr(); C1 objeto(1, 2, 3); objeto.muestra(); getch(); } 2008 (c) Luis Hernández Programación en Ingeniería Electrónica | Programación Básica en C++ 80 14. Funciones Virtuales Una función virutal es miembro de una clase que se declara dentro de una clase base y se redefine en una clase derivada. Para crearla hay que comenzar la declaración de la función con la palabra clave virtual. Debe tener el mismo tipo y numero de parametros y devolver el mismo tipo. La redefinición de la función virtual en una clase derivada expresa el funcionamiento especifico de la misma con respecto a esa clase derivada. Al redefinir una función virtual en una clase derivada no es necesario poner virtual. 2008 (c) Luis Hernández Programación en Ingeniería Electrónica | Programación Básica en C++ 81 14.1. Ejemplo class base{ public: int i; base(int x){i=x;} virtual void func(){cout<<i<<"\n";} }; class derivada1:public base{ public: derivada1(int x):base(x){}; void func(){ cout <<i*i<<"\n";} }; 2008 (c) Luis Hernández Programación en Ingeniería Electrónica | Programación Básica en C++ 82 14.1. Ejemplo class derivada2:public base{ public: derivada2(int x):base(x){}; void func(){cout<<i+i;} }; void main() { base obj1(10); derivada1 obj2(10); derivada2 obj3(10); obj1.func(); // =i obj2.func(); // =i*i obj3.func(); // =i+i getch(); } 2008 (c) Luis Hernández Programación en Ingeniería Electrónica | Programación Básica en C++ 83 15. Sobrecarga Sobrecarga de Funciones Argumentos implícitos Sobrecarga de Operadores 2008 (c) Luis Hernández Programación en Ingeniería Electrónica | Programación Básica en C++ 84 15.1. Sobrecarga de Funciones En C++, cuando dos o más funciones tienen el mismo nombre y realizan operaciones distintas se dice que son funciones sobrecargadas. También es posible y muy común sobrecargar las funciones constructoras. Las razones para sobrecargar las funciones constructoras son: ganar flexibilidad, soportar arrays en el proceso y permitir copias de constructores. 2008 (c) Luis Hernández Programación en Ingeniería Electrónica | Programación Básica en C++ 85 15.1.1. Ejemplo int abs(int num); long abs(long num); double abs(double num); void main() { clrscr(); cout <<"abs(-10) "<< abs(-10) <<"\n"; cout <<"abs(-10L) "<< abs(-10L) <<"\n"; cout <<"abs(-10.01) "<< abs(-10.01) <<"\n"; getch(); } 2008 (c) Luis Hernández Programación en Ingeniería Electrónica | Programación Básica en C++ 86 15.1.1. Ejemplo int abs(int num) { return num<0 ? -num:num; } long abs(long num) { return num<0 ? -num:num; } double abs(double num) { return num<0 ? -num:num; } 2008 (c) Luis Hernández Programación en Ingeniería Electrónica | Programación Básica en C++ 87 15.1.2. Ejemplo void fecha(char *fecha); void fecha(int anno, int mes, int dia); void main() { fecha("23/8/98"); fecha(98, 8, 23); getch(); } void fecha(char *fecha) { cout<<"Fecha: "<<fecha<<"\n"; } void fecha(int anno,int mes,int dia) { cout<<"Fecha: "<<dia<<"/"<<mes<<"/"<<anno; } 2008 (c) Luis Hernández Programación en Ingeniería Electrónica | Programación Básica en C++ 88 15.2. Argumentos Implícitos Otra característica relacionada con la sobrecarga es la utilización de argumentos implícitos. Permite dar un valor a un parámetro cuando no se especifica el argumento correspondiente en la llamada a la función. 2008 (c) Luis Hernández Programación en Ingeniería Electrónica | Programación Básica en C++ 89 15.2.1. Ejemplo void funcion(int a=0, int b=0) { cout<<"a: "<< a <<" b: "<< b <<"\n"; } void main() { clrscr(); funcion(); funcion(10); funcion(20, 30); getch(); } 2008 (c) Luis Hernández Programación en Ingeniería Electrónica | Programación Básica en C++ 90 15.3. Sobrecarga de Operadores Similar a la de funciones, un operador siempre se sobrecarga con relación a una clase. Cuando se sobrecarga un operador, no pierde su contenido original, gana un contenido relacionado con la clase. Para sobrecargar un operador se crea una función operadora que normalmente será una función amiga a la clase. La sobrecarga tiene dos restricciones: no puede cambiar la precedencia del operador y el numero de operadores no puede modificarse. Hay operadores que no pueden sobrecargarse. 2008 (c) Luis Hernández Programación en Ingeniería Electrónica | Programación Básica en C++ 91 15.3. Sobrecarga de Operadores Operadores binarios Operadores logicos-relacionales Operadores unarios 2008 (c) Luis Hernández Programación en Ingeniería Electrónica | Programación Básica en C++ 92 15.3.1. Binarios La función solo tendrá un parametro. Este parámetro contendrá al objeto que este en el lado derecho del operador. El objeto del lado izquierdo es el que genera la llamada a la función operadora y se pasa implícitamente a través de this. 2008 (c) Luis Hernández Programación en Ingeniería Electrónica | Programación Básica en C++ 93 15.3.1.1. Ejemplo class opera{ int x, y; public: opera() {x=0;y=0;} opera(int i, int j) {x=i; y=j;} void obtenxy(int &i,int &j) {i=x; j=y;} opera operator+(opera obj); }; opera opera::operator+(opera obj) { opera temp; temp.x=x+obj.x; temp.y=y+obj.y; return temp; } 2008 (c) Luis Hernández Programación en Ingeniería Electrónica | Programación Básica en C++ 94 15.3.1.1. Ejemplo void main() { opera obj1(10, 10), obj2(5, 3),obj3; int x,y; obj3=obj1+obj2; obj3.obtenxy(x,y); cout << "Suma de obj1 y obj2\n "; cout << "Valor x: "<< x << " Valor y: " << y; getch(); } 2008 (c) Luis Hernández Programación en Ingeniería Electrónica | Programación Básica en C++ 95 15.3.1. Lógicos y Relacionales Cuando se sobrecargan dichos operadores, las funciones operadoras no devuelverán un objeto, en lugar de ello, devolverán un entero que indique verdadero o falso. Esto permite que los operadores se integren en expresiones lógicas y relacionales más extensas que admitan otros tipos de datos. 2008 (c) Luis Hernández Programación en Ingeniería Electrónica | Programación Básica en C++ 96 15.3.1.1. Ejemplo class opera{ int x,y; public: opera() {x=0;y=0;} opera(int i,int j) {x=i; y=j;} void obtenerxy(int &i, int &j) {i=x; j=y;} int operator==(opera obj); }; int opera::operator==(opera obj) { if(x==obj.x && y==obj.y) return 1; else return 0; } 2008 (c) Luis Hernández Programación en Ingeniería Electrónica | Programación Básica en C++ 97 15.3.1.1. Ejemplo void main() { clrscr(); opera obj1(10, 10), obj2(5, 3); if(obj1==obj2) cout << "Obj1 y Obj2 son iguales"; else cout << " Obj1 y Obj2 son diferentes"; getch(); } 2008 (c) Luis Hernández Programación en Ingeniería Electrónica | Programación Básica en C++ 98 15.3.2. Unarios El miembro no tiene parámetro. Es el operando el que genera la llamada a la función operadora. Los operadores unarios pueden preceder o seguir a su operando, con lo que hay que tener en cuenta como se realiza la llamada. 2008 (c) Luis Hernández Programación en Ingeniería Electrónica | Programación Básica en C++ 99 15.3.2.1. Ejemplo class opera{ int x, y; public: opera() {x=0;y=0;} opera(int i, int j) {x=i;y=j;} void obtenxy(int &i, int &j) {i=x; j=y;} opera operator++(); }; opera opera::operator++() { x++; y++; } 2008 (c) Luis Hernández Programación en Ingeniería Electrónica | Programación Básica en C++ 100 15.3.2.1. Ejemplo void main() { clrscr(); opera objeto(10, 7); int x,y; objeto++; objeto.obtenxy(x,y); cout<< "Valor x: " << x; cout <<" Valor y: "<< y << "\n"; getch(); } 2008 (c) Luis Hernández Programación en Ingeniería Electrónica | Programación Básica en C++ 101 16. Ficheros Para realizar E/S de ficheros debe incluirse en el programa el archivo de cabecera fstream.h. Un fichero se abre mediante el enlace a un flujo y antes de abrir un fichero debe obtenerse el flujo asociado. Los flujos tienen funciones constructoras que abren el fichero automáticamente. Tipos de flujo: de salida (ofstream out), de entrada (ofstream in) y de salida-entrada (fstream io). 2008 (c) Luis Hernández Programación en Ingeniería Electrónica | Programación Básica en C++ 102 16. Ficheros Existen diferentes tipos de fichero: secuencial, binario sin formato y de acceso aleatorio. Todos los tipos de fichero comparten el método de apertura, pero cada uno de ellos tienen métodos propios para ir escribiendo y leyendo. Una vez realizadas las operaciones con los ficheros, debemos cerrarlo mediante la función close( ). 2008 (c) Luis Hernández Programación en Ingeniería Electrónica | Programación Básica en C++ 103 16.1. Secuencial void main() { ofstream out("fichero.tex"); if (!out) { cout << "Error de apertura"; exit(1); } char cad[80]; cout << "Para salir dejar en blanco\n"; do { cout<<": "; gets(cad); out << cad << endl; } while(*cad); out.close(); } 2008 (c) Luis Hernández Programación en Ingeniería Electrónica | Programación Básica en C++ 104 16.2. Binarios sin Formato Las funciones de E/S son read() y write(). La función read() lee un número determinado de bytes del flujo asociado y los coloca en la variable. La función write() escribe un número determinado de bytes de la variable en el flujo asociado. 2008 (c) Luis Hernández Programación en Ingeniería Electrónica | Programación Básica en C++ 105 16.2.1. Ejemplo void main() { ofstream out("texto.tex"); if (!out) { cout << "Error de apertura"; exit(1); } char cad[80]; cout << "Para salir dejar en blanco\n"; do { cout<<": "; gets(cad); out.write(cad,strlen(cad)); } while(strlen(cad)); out.close(); } 2008 (c) Luis Hernández Programación en Ingeniería Electrónica | Programación Básica en C++ 106 16.2.2. Ejemplo void main() { clrscr(); ifstream in("texto.tex"); if (!in) { cout << "Error de apertura"; exit(1); } char cad[80]; cout << "Lectura de cadenas\n"; in.read(cad, 80); cout << cad; in.close(); getch(); } 2008 (c) Luis Hernández Programación en Ingeniería Electrónica | Programación Básica en C++ 107 16.3. Aleatorios Las funciones que se utilizan son seekg() y seekp() para posicionarnos y las funciones get() y put() para leer y escribir en el fichero. Las funciones de posicionamiento y leer-escribir van emparejadas. Tipos de posicionamiento: desde el principio (ios::beg), desde el final (ios::end) y posición actual (ios::cur). 2008 (c) Luis Hernández Programación en Ingeniería Electrónica | Programación Básica en C++ 108 16.3.1. Ejemplo void main() { fstream out("texto1.txt",ios::in|ios::out); if (!out) { cout << "El archivo no se puede abrir"; exit(1); } out.seekp(4,ios::beg); out.put('z'); out.close(); } 2008 (c) Luis Hernández Programación en Ingeniería Electrónica | Programación Básica en C++ 109 17. Excepciones Es un mecanismo que permite gestionar y responder a los errores en tiempo de ejecución. Las excepciones están construidas a partir de las palabras clave: try, catch y throw. Cualquier sentencia que provoque una excepción debe ser ejecutada desde un bloque try o desde una función que este dentro del bloque try. Cualquier excepción debe ser capturada por una sentencia cath que siga a la sentencia try, causante de la excepción. 2008 (c) Luis Hernández Programación en Ingeniería Electrónica | Programación Básica en C++ 110 17.1. Ejemplo void main() { try{ cout<<"Dentro del bloque try\n"; throw 10; cout<<"Ejecucion sin errores"; } catch(int i){ cout<<"Capturado el error "<< i; cout<<"\n"; } cout << "fin"; getch(); } 2008 (c) Luis Hernández Programación en Ingeniería Electrónica | Programación Básica en C++ 111