curso 0: programación orientada a objetos (poo) · nuevos en c++: bool : tipo booleano ......
TRANSCRIPT
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Curso 0: Programación orientada a objetos (POO)
Iván Alduán ([email protected])
1
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Introducción a C++ Introducción al entorno de Visual Studio Programación de pequeños ejemplos en C++
3
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Programación
La programación es el proceso de diseñar, escribir, depurar y mantener el código fuente de programas computacionales
Ficheros fuente y programa o código fuente Pensados para que los comprendan los seres humanos Lenguaje de programación de alto nivel: C/C++, Java, C#, …
Ficheros objeto, código objeto y compiladores compilador = traduce el programa fuente a su código objeto equivalente
(un fichero objeto por cada translation unit) Ficheros ejecutables, librerías y enlazadores
Es necesario unir todos los ficheros objeto, más las librerías en un único fichero ejecutable (o librería)
Link o enlazador = combina todos los ficheros que forman nuestro programa y crea el fichero ejecutable
4
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Errores
Errores de sintaxis Son errores en el programa fuente. Pueden deberse a palabras
reservadas mal escritas, expresiones erróneas o incompletas El compilador nos dará una lista de errores de sintaxis
Errores de enlazado El programa enlazador también puede encontrar errores,
funciones que no están definidas en ninguno de los ficheros objetos ni en las librerías
Puede que hayamos olvidado incluir alguna librería Errores de ejecución El programa terminará bruscamente Existen programas auxiliares para buscar estos errores, son los
llamados depuradores (debuggers) Errores de diseño
5
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
IDEs y Microsoft Visual Studio
Integrated Development Environment Proveen un marco de trabajo amigable con acceso a todas las
herramientas necesarias para desarrollar programas Editor de código
Resaltado de sintaxis, indicador de errores, autocompletado Compilador y Enlazador automáticos
Si fallan te indican el motivo con bastante exactitud Depurador
Ayuda a caminar a través de nuestro programa para detectar errores de ejecución: pila, breakpoint, watch
Constructor de interfaces gráficas WYSIWIG (Plataforma .Net) Microsoft Visual Studio Versión Express gratuita (no plugins :/ ) Versión Professional gratuita a través de DreamSpark
6
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
La función main en C++
C++ es un superconjunto de C Aunque existen algunas diferencias entre ambos
int main(): es la función que hace de punto de entrada del programa. Todo programa en C++ debe tener un función main
7
int main(int argc, char *argv[]) { int numero; numero = 2 + 2; return 0; }
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Example 01 – Hello World
Comprobando que a todos nos funciona el IDE
8
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Tipos de datos fundamentales C++
Heredados de C:
void : no asociado a ningún tipo char : caracter int : entero float : número en coma flotante, precisión simple double : número en coma flotante, doble precisión
Nuevos en C++: bool : tipo booleano wchar_t, char16_t, char32_t : caracter ancho (Unicode)
Librería estándar de C++: std::string : cadenas de caracteres
9
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Modificadores de tipos C++
10
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Operadores C++
Aritméticos: +, -, *, /, %, : suma, resta, multiplicación, división, resto a++, ++a, a--, --a : postincremento, preincremento, postdecremento
Asignación: x = <<expresión>> : asigna a x el valor de evaluar <<expresión>> +=, -=, *=, /= : suma, resta, multiplicación y división con asignación
Ejemplo: a += b; es equivalente a: a = a + b;
Manejo de bits: &, |, ^, ~ : and, or, xor y not binarios << , >> : desplazamiento a izquierda y a derecha
Lógicos: &&, ||, ! : and, or, not (devuelven un bool)
11
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Operadores C++
Relacionales: >, >=, <, <=, ==, != : mayor, mayor o igual, menor, menor o igual, .. (devuelven un bool)
de Preproceso: #define, #line, #pragma ….
de Puntero: Operadores de indirección (*) y de referencia (&)
Manejo de memoria: new y delete
Otros: :: , .* , ->* , ? : , sizeof(), typeid() ....
12
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Operadores C++
Precedencia Prioridad de unos
operadores frente a otros Puede modificarse con
paréntesis
Asociatividad define el orden de
ejecución para operadores con idéntica precedencia
13
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Sentencias C++
Expresiones Declaración de variables <tipo> <identificador>; Asignación <variable> = <expresion>; Llamada a función <funcion>(<lista_parametros>);
Bucles for (<inicializacion>; <condicion>; <incremento>) <sentencia> while (<condicion>) <sentencia> do <sentencia> while (<condicion>)
Selección if (<condicion>) <sentencia1> else <sentencia2> switch (<variable) case <expresion>: <sentencia>
14
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Example 02 – Múltiplos de 3
Usando diferentes tipos de sentencias
15
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Funciones C++
En C++ es obligatorio usar prototipos. Un prototipo es una declaración de una función antes de ser utilizada dicha función
Las funciones se deben definir en alguna parte, implementando su funcionalidad (cuerpo) Pueden estar en librerías externas, otros ficheros fuentes, etc
16
//Declaración de la función int media(int, int); ... //Definición de la función int media(int a, int b) { int result; result = (a + b)/2; return result; }
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Funciones C++
La estructura de un programa en C++ quedaría así
17
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Funciones C++ Recursividad
Una función es recursiva si durante su ejecución tiene una llamada a si misma
Se distingue entre: Recursividad directa Recursividad indirecta: varias se llaman unas a otras
formando ciclos Toda función recursiva ha de presentar al menos una
condición de terminación Ejemplos: Cálculo del factorial mediante recursividad directa
18
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Example 03 – Factorial
Usando funciones, el debugger y la pila de llamadas
19
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Ámbito de variables y funciones
Una variable es global si se declara fuera de cualquier función. Se puede acceder a ella desde cualquier función Una variable global estática sólo es visible en la unidad de
compilación en la que se declara
Las variables locales se declaran dentro de una función o bloque, y solo son visibles desde el bloque donde se declaran Los parámetros de una función son variables locales Una variable local estática conserva el valor entre distintas
llamadas a la función
20
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Ámbito de variables y funciones
21
/* Variables globales */ int i; int j = 10; float k, l; static char m; static int funcion_1() { /* Variables locales */ char d = ‘A’; static int call = 0; … call++; … return call; }
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Conversión de tipos
Implícita: En expresiones el tipo mas bajo promociona al mas alto
long double > double > float > unsigned long long > long long > unsigned long > long > unsigned int > int > unsigned short > short > unsigned char > char
En asignaciones el valor del lado derecho se convierte al tipo de la variable de la izquierda
Explicita (casting) (tipo) expresion
22
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Constantes C++
Varias formas de declararlas: Usando la directiva del preprocesador #define: #define MAX_SIZE 64
Usando un tipo enumerado: enum{
MAX_SIZE = 64,
};
Usando const : const int MAX_SIZE = 64;
23
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Arrays C/C++
Son variables que contienen una colección consecutiva de datos
Se declaran entre corchetes, y su tamaño debe ser fijado en tiempo de compilación
Se accede a los elementos también entre corchetes. Los índices comienzan en 0, y no hay comprobación
24
int a[10]; //array de 10 ints float b[2][10] //array de 2 dimensiones . . . a[0] = 10; b[1][4] = 5.3; a[20] = 123; //esto no da error de compilación
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Inicialización de Arrays
Al declarar un array se le puede dar valores iniciales a sus elementos:
Si no se especifica el tamaño, tomará el del número
de elementos inicializados. Si se inicializan menos del tamaño, los no
inicializados tendrán basura. Si se inicializan más del tamaño, el compilador dará
un aviso. 25
int a[4] = {13, 1, 27, 1289}; int b[] = {1, 3, 5, 7, 9}; int c[4] = {23, 12}; //c[2] y c[3] sin inicializar int d[2] = {12, 24, 91, 103}; //warning
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Punteros C/C++
Un puntero es una variable que representa una posición de memoria que contiene un dato
Se declaran anteponiendo un * al nombre de la variable.
Admiten el valor NULL (definido en cstdlib)
26
int *a; // puntero a entero float *b; // puntero a flotante char *c; // puntero a caracter
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Operadores de punteros
Operaciones: El operador * dereferencia el puntero. Es decir, se accede
al valor apuntado El operador & devuelve la dirección de memoria donde se
encuentra una variable. Es decir se obtiene un puntero a la variable
27
int a = 0; int *b; b = &a; // b apunta a la dirección donde está a *b = 127; // se guarda 127 en la dir. apuntada por b //En este punto la variable a tiene valor 127
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Operadores de punteros
Operaciones: Los punteros se pueden sumar, restar, etc Esas operaciones se hacen en múltiplos del tamaño del
dato apuntado
28
int *a = . . . . //a apunta a algún lugar a = a + 1; //ahora apunta sizeof(int) más adelante // a apunta a la dir. del siguiente int en memoria a = a + 4; //ahora apunta 4*sizeof(int) más adelante
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Arrays y punteros
Los arrays se pueden comportar como punteros, y los punteros como arrays
Una variable de tipo array es un puntero al primer elemento del array
Un puntero al primer elemento de una colección consecutiva puede usarse como un array
29
int a[16]; //array de 16 elementos *a = 10; // Es lo mismo que a[0] = 10; *(a + 3) = 20; // Es lo mismo que a[3] = 20; int *b = (int *) malloc (8*sizeof(int)); //b es un puntero a un espacio de memoria en el //que caben 8 ints b[6] = 123; // Es lo mismo que *(b + 6) = 123;
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Arrays y punteros
Diferencias: Un array tiene un tamaño asociado, un puntero no Un array es como un puntero constante, no se puede
cambiar el lugar al que apunta Un array está definido en memoria estática y un puntero
puede apuntar a memoria dinámica
30
int a[16]; //array de 16 elementos int s1 = sizeof(a); //s1 valdrá 16*sizeof(int) int *b = (int *) malloc (128*sizeof(int)); //b es un puntero a una colección de 128 int int s2 = sizeof(b); //s2 valdrá 4 u 8, que es el //tamaño de una dirección
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Memoria dinámica
Stack o Pila (Memoria estática) Variables locales (dentro de un bloque) Va aumentando acumulando bloques de variables encima a
medida que entramos a más funciones El programa la gestiona automáticamente (FIFO) Tamaño muy limitado (1MB – 32MB)
Heap o Montículo (Memoria dinámica) Grueso de memoria no utilizado por ningún programa Podemos reservar memoria dinámicamente Enorme cantidad de memoria Tenemos que gestionarla los programadores
31
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
malloc y free (C/C++)
Ejemplo:
32
int *a, *b; // punteros a enteros //se reserva espacio en memoria para un entero //a apunta a ese espacio de memoria a = (int *) malloc (1*sizeof(int)); //se reserva espacio en memoria para 16 enteros //b apunta a ese espacio de memoria b = (int *) malloc (16*sizeof(int)); //se libera el espacio del primer malloc free(a); //se libera el espacio del segundo malloc free(b);
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
new y delete (C++)
Para realizar esta administración de la memoria dinámica, C++ cuenta con dos operadores new y delete
El operador new reserva memoria dinámica para cualquier tipo tipos primitivos (int, double) tipos definidos por el usuario (clases o registros)
delete se encarga de liberar la memoria previamente reservada Pueden aplicarse para reservar elementos individuales o arrays
33
int *a, *b; a = new int; b = new int[100000000]; delete a; delete[] b;
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Example 04 – Ordenación de un vector
Usando watch para inspeccionar el valor de punteros
34
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Registros C++
Son tipos compuestos formados por elementos heterogéneos
Dentro del registro cada elemento tiene un identificador y un tipo.
35
//Definición del registro struct Complejo { float real; float imag; }; //Declaración de variables del tipo registro Complejo uncomplejo, otrocomplejo;
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Registros C++
Para acceder a los elementos de un registro estructura se utiliza el operador punto (.)
Si se trata de un puntero a registro se puede atajar con el operador flecha (->)
36
uncomplejo.real = 1.3; uncomplejo.imag = 2.7;
Complejo *a = (Complejo *)malloc(sizeof(Complejo)); a->real = 2.4; //lo mismo que (*a).real = 2.4; a->imag = 3.14; //lo mismo que (*a).imag = 3.14;
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
std::strings (C++)
En C++ si existe un tipo de datos para strings También se utilizan arrays de char acabados con el
caracter ‘\0’ como en C Una cadena de caracteres entre comillas dobles es un
inmediato que representa un string
37
#include<cstring> std::string s = “Esto es un tipo cadena”; char s1[] = “Hola”; char *s2 = “Hola”; char *s3[] = {‘H’, ‘o’, ‘l’, ‘a’, ‘\0’} std::string s4(s1); // convertir a string int n = s4.length(); // longitud de la cadena
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Argumentos de funciones (C++)
Los argumentos por defecto siempre se pasan por valor Pasar un argumento por valor copia todo su contenido No se deben pasar nunca objetos pesados por valor Podríamos pasar punteros a los objetos
Con paso por referencia la sintaxis es mucho más amigable sin tener que aplicar los operadores de punteros Internamente funcionan como punteros
38
//Ejemplo de paso de argumentos por referencia void intercambia(int &a, int &b) { int aux = a; a = b; b = aux; } int x = 10, y = 20; Intercambia(x, y);
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Example 05 – Palíndromos
Operando con std::string
39
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Espacios con nombre (C++)
Nos ayudan a evitar problemas con identificadores iguales en grandes proyectos Diferentes librerías puede que usen los mismos nombres
para cosas diferentes, de modo que resulta imposible integrar esas librerías en la misma aplicación
40
namespace mathlib { int max(int a, int b); int min(int a, int b); struct Vector { float x, y, z; }; ... }
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Espacios con nombre (C++)
El nombre del espacio funciona como un prefijo para las variables, funciones o clases declaradas en su interior
Para acceder a una de esas variables se tiene que Usar un especificador de ámbito (::) activar el espacio con nombre adecuado
41
mathlib::vector v; int n = mathlib::max(10, 15); using namespace mathlib; Vector w; int m = min(10, 15);
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Librerías externas en Windows
Una librería es un conjunto de recursos (algoritmos) prefabricados, que pueden ser utilizados por el programador para realizar determinadas operaciones
Windows: librerías estáticas (.lib) y librerías dinámicas (.dll) MSBUILD: librerías de importación (.lib)
Necesitamos tres cosas Archivos de definición o includes Las librerías a importar dentro de nuestro programa (.lib) Si procede, que el programa tenga acceso a la librería dinámica
cuando entre en ejecución (.dll) Mismo directorio que el ejecutable PATH del sistema operativo
42
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Example 06 – GLUT Cube
Usando librerías externas y pintando gráficos 3D
43
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Bibliografía recomendada
S.B. Lippman – C++ Primer (5th) – 2012 B. Stroustrup – The C++ Programming Language (4th) – 2013
44
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Programación orientada a objetos (POO)
45
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Programación Orientada a Objetos
La programación orientada a objetos es una forma de programar que trata de encontrar una solución más intuitiva para la resolución de problemas complejos
Exige un cambio de mentalidad para diseñar aplicaciones y programas informáticos ahora más complejos No buscamos directamente el encontrar la secuencia exacta de las
instrucciones necesarias para resolver el problema Queremos abstraernos a un nivel más conceptual para dividir el problema
en una serie de elementos que interaccionando entre sí den solución al problema
La idea básica de este tipo de programación es agrupar los datos y los procedimientos para manejarlos en entidades únicas con un significado a las que llamaremos objetos
Un programa es un objeto, que a su vez está formado de otros objetos que interactúan entre sí
46
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Objeto
Un objeto es una unidad con cierto significado que engloba en sí mismo: Un conjunto de datos que definen su estado Los procedimientos necesarios para el tratamiento de esos
datos con facilidad Ejemplos de objetos del inundo real son: pasajero,
asiento, avión, vuelo, aeropuerto Por ejemplo, los atributos de un pasajero incluyen el nombre, la
edad, el sexo, la fecha de nacimiento, la dirección, etc El comportamiento es el conjunto de cosas que puede hacer un
objeto; por ejemplo, un pasajero puede estudiar, trabajar, comer, dormir, etc
47
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Objeto
Posible ejemplo de un objeto dentro de una aplicación encargada de gestionar unos cines
Otros objetos en la aplicación podrían ser cine, empleado, sala, proyector, butaca, espectador, entrada
48
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Objeto: conceptos
Propiedades o atributos: Características o variables que definen a un objeto
Métodos: Funciones disponibles en el objeto para manipular o modificar los atributos del mismo
Mensaje: El mensaje es el modo en el que se comunican los objetos entre sí En realidad, esto no es mas que una llamada a un método
de un determinado objeto
49
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Programa OO vs OP
El resultado final del proceso es un programa de computadora que contiene características que representan algunos de los objetos del mundo real que son parte del suceso
50
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Ventajas
Ventajas de la programación orientada a objetos Diseños más cercanos al mundo real Más fáciles de diseñar y mantener Facilidad de comunicación entre todos los roles implicados
en el desarrollo: usuarios, clientes, analistas, diseñadores, programadores
Facilita la reutilización de código ya que cada objeto tiene significado propio Cada objeto es independiente del resto Ejemplo: Una clase Vector3 la podremos reutilizar en todas
nuestras aplicaciones de gráficos
51
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Clases
Una clase define un patrón para construir objetos Es importante distinguir entre objetos y clases La clase es simplemente una declaración, patrón o tipo Los objetos son los ejemplares concretos de una clase.
Cuando creamos un ejemplar tenemos que especificar la clase a partir de la cual se creará Por ejemplo, un objeto de la clase película sería Toy Story
52
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Clases en C++
Las clases C++ permiten definir nuevos tipos de datos Cada clase es un nuevo tipo Cada elemento de la clase se caracteriza por ciertos valores
y las operaciones disponibles para crear dichos elementos, modificarlos y destruirlo
Podemos establecer un paralelismo entre los tipos de datos vistos hasta el momento (int, char, array, struct, …) y las clases Ambos son tipos Pueden declararse elementos de ese tipo
En los tipos por defecto los llamábamos variables En el caso de una clase los llamaremos instancias u objetos
53
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Clases en C++
Características fundamentales de las clases en C++
Nombre de la clase. Sirve para identificar a todos los objetos que tengan unas determinadas características
Conjunto de atributos. Datos miembro. El valor de los atributos representan el estado de cada objeto.
Conjunto de métodos. Funciones miembro. Permite que los objetos cambien de estado, dependiendo del estado anterior que tuviera el objeto.
Niveles de acceso para proteger ciertos miembros de la clase. Normalmente, se definirán como ocultos (privados) los atributos y visibles (públicos) los métodos.
54
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Declaración de clases en C++
55
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Paso de mensajes
56
Una vez creados los objetos, podemos trabajar con ellos. Si queremos que un determinado objeto ejecute un método, utilizamos el operador punto (•).
A esto se le conoce como paso de mensajes. Cada paso de mensaje provoca la ejecución del correspondiente
método definido en la clase del objeto receptor Cada objeto entiende tantos mensajes como métodos estén definidos
en su clase
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Ocultación / Encapsulamiento
La clave de la programación orientada a objetos es el encapsulamiento de todo el código y detalles de implementación bajo interfaces de manejo sencillo
La definición de una clase en C++ viene dada por: Un archivo de cabecera (.h)
Define la interfaz de la clase de forma clara, es decir, qué métodos ofrece el módulo definido, sin detalles de implementación
Un archivo fuente (.cpp) Define los detalles de implementación de la clase Inclusión de su correspondiente fichero de cabecera (#include) Definición de funciones declaradas y no declaradas en el fichero
de cabecera
57
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Especificadores de acceso
Dentro de la lista de miembros, cada miembro puede tener diferentes niveles de acceso
Public: miembros accesibles desde cualquier parte Private: sólo son accesibles por la propia clase Protected: nos faltan conocimientos para entenderlo
58
class <identificador de clase> { public: <lista de miembros> private: <lista de miembros> protected: <lista de miembros> };
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Especificadores de acceso
Por lo general Los atributos deben ser privados Los métodos o funciones miembro deben ser públicas A través del objeto de una clase sólo se puede acceder a lo que está
declarado como público en la clase Lo privado solo puede ser manipulado internamente desde el código
de los métodos
59
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
El puntero this
Todos los objetos de una clase comparten la misma copia de las funciones de esa clase ¿cómo hace una función miembro para referirse a un dato
de un objeto en concreto?
La respuesta es: usando el puntero this cada objeto tiene asociado un puntero a si mismo que se
puede usar para manejar sus miembros generalmente su uso es transparente al programador, pero
a veces es necesario invocarlo de manera explícita
60
void pareja::Guarda(int a_input, int b) { a = a_input; // equivale a this->a = a_input; this->b = b;
}
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Diseño conceptual
Para representar gráficamente las clases y objetos, se utilizan diagramas conceptuales basados en UML (Lenguaje de Modelado Unificado)
61
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Resumen
Las instancias de un tipo cualquiera se denominan variables, mientras que las instancias de una clase se denominan objetos
Los atributos describen el estado de un objeto. Un atributo consta de dos partes: nombre del atributo y valor.
Los métodos describen el comportamiento de los objetos de una clase. Representan las operaciones que se pueden realizar con los objetos de la clase. La ejecución de un método puede conducir a cambiar el estado del objeto.
Los objetos se manipulan mediante el paso de mensajes. Para ejecutar un método asociado a un objeto, se realiza una acción que se conoce como “envío de mensajes”.
Se denomina encapsulamiento al ocultamiento del estado, es decir, de los datos miembro, de un objeto Las operaciones y datos visibles desde el exterior de la clase es lo que
se denomina interfaz de la clase
62
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
El poder de la POO
Constructores y destructores Sobrecarga de operadores y métodos Métodos estáticos Herencia Interfaces Clases abstractas Funciones virtuales
Polimorfismo Plantillas Excepciones
63
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Constructores
Los constructores son funciones miembro especiales que sirven para inicializar un objeto
Tienen el mismo nombre que la clase, no retornan ningún valor y no pueden ser heredados
Por norma general deben ser públicos ya que siempre se usan desde el exterior de la clase en un patrón de diseño singleton precisamente nos
interesa lo contrario, que el constructor esté oculto
Si no declaramos ningún constructor, el compilador lo hará por nosotros creando uno por defecto
64
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Constructores
Ejemplo:
65
class pareja { public:
// Constructor pareja(int a2, int b2); // Funciones miembro de la clase "pareja" void Lee(int &a2, int &b2); void Guarda(int a2, int b2);
private: // Datos miembro de la clase "pareja" int a, b;
public: }; pareja::pareja(int a2, int b2) {
a = a2; b = b2;
}
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Constructores
Cuando se use un constructor sin parámetros para declarar un objeto no se deben escribir los paréntesis error frecuente cuando se empiezan a usar clases
Si un constructor requiere argumentos, es obligatorio suministrarlos
66
pareja par1(12,43); pareja par2(45,34); pareja par1(); //ERROR -> El compilador piensa que es un //prototipo de una función pareja par1;
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Constructores
Hay un modo más seguro de inicializar los datos miembros de los objetos en los constructores Inicializadores: Cada inicializador consiste en el nombre de
la variable miembro a inicializar, seguida de la expresión que se usará para inicializarla entre paréntesis
Pregunta: ¿Qué pasa si dentro de nuestra clase tenemos como
atributo un objeto sin constructor por defecto? ¿Eficiencia?
67
pareja::pareja(int a2, int b2) : a(a2), b(b2) {}
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Constructores
Sobrecarga de constructores podemos definirse varios constructores para cada clase
Argumentos por defecto reducir el número de constructores necesarios
68
pareja(int a2, int b2) : a(a2), b(b2) {} pareja() : a(0), b(0) {}
pareja(int a2=0, int b2=0) : a(a2), b(b2) {}
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Constructores
Constructor copia crea un objeto a partir de otro objeto existente un argumento que es una referencia a un objeto de su
misma clase si no se define, el compilador crea uno por defecto
Asignación de objetos copia los valores de los datos miembro
69
pareja(const pareja &p); pareja::pareja(const pareja &p) : a(p.a), b(p.b) {}
pareja par1(12, 32), par2; par2 = par1;
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Destructores
Los destructores son funciones miembro especiales que sirven para definir cómo se elimina un objeto de una determinada clase
Tienen el mismo nombre que la clase, pero con el símbolo ~ delante, no retornan ningún valor y no pueden ser heredados
En general, será necesario definir un destructor cuando nuestra clase tenga datos miembro de tipo puntero
Pregunta: ¿Tiene sentido la sobrecarga de destructores?
70
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Ejemplo: Clase cadena
71
class cadena { public:
cadena(char *c); cadena(const cadena &); // ¿Por qué es necesario definirlo? ~cadena(); // ¿Por qué es necesario definirlo? void Set(char *dest); char* Get();
private: char *cad; // cadena de caracteres
}; cadena::cadena(char *c) {
cad = new char[strlen(c)+1]; strcpy(cad, c); // Almacena la cadena
} …
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Ejemplo: Clase cadena
72
… cadena::~cadena() {
delete[] cad; // Libera la memoria reservada a cad } cadena::cadena(const cadena &c) {
if(&c == this) { cout << "Sí, soy yo." << endl; this->cad = c.cad;
} else {
cout << "No, no soy yo." << endl; this->cad = new char[strlen(c.cad)+1]; strcpy(this->cad, c.cad);
} return c;
}
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Operadores sobrecargados
Podemos redefinir cualquier operando aplicado a una clase para que funcione como nosotros deseemos
Cuando se sobrecargan operadores en el interior de una clase se asume que un operando es el propio objeto de la clase por lo que no hay que declararlo
Cuando nuestra clase tenga punteros es posible que necesitemos sobrecargar el operador asignación (=) Pensar en los problemas anteriores del constructor copia
por defecto
73
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Sobrecarga de operadores
74
class Tiempo { public: Tiempo(int h=0, int m=0) : hora(h), minuto(m) {} Tiempo operator+(const Tiempo &h); Tiempo operator*(const Tiempo &h); ¿tiene sentido? private: int hora; int minuto; }; Tiempo Tiempo::operator+(const Tiempo &h) { Tiempo temp; temp.minuto = minuto + h.minuto; temp.hora = hora + h.hora; if(temp.minuto >= 60) { temp.minuto -= 60; temp.hora++; } return temp; }
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Operadores sobrecargados
Problema: ¿Cómo sobrecargamos un operador unitario sufijo?
75
class Tiempo { ... Tiempo& operator++(); ...
}; Tiempo& Tiempo::operator++() {
minuto++; while(minuto >= 60) {
minuto -= 60; hora++;
} return *this;
} Tiempo t1; ++t1; ¿t1++;?
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Operadores sobrecargados
Problema: ¿Cómo sobrecargamos el operador unitario sufijo? no hay forma de decirle al compilador cuál de las dos
modalidades del operador estamos sobrecargando, así que los compiladores usan una regla: si se declara un parámetro para un operador ++ ó – se sobrecargará la forma sufija del operador
76
Tiempo Tiempo::operator++(int) { Tiempo temp(*this); // Constructor copia minuto++; while(minuto >= 60) {
minuto -= 60; hora++;
} return temp;
}
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Métodos sobrecargados
Sobrecarga de métodos Las funciones miembros de las clases también pueden
sobrecargarse
Argumentos por defecto En las funciones miembros de las clases también pueden
usarse parámetros con valores por defecto
77
void Vector3D::Asignar(float xi, float yi=0, float zi=0) { x = xi; y = yi; z = zi;
} void Vector3D::Asignar(const Vector3D &p) {
Asignar(p.x, p.y, p.z); }
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Sistema de protección
Especificadores de acceso public: private: protected:
Declaraciones friend El modificador "friend" puede aplicarse a clases o funciones
para inhibir el sistema de protección Las relaciones de "amistad" entre clases son parecidas a las
amistades entre personas: la amistad no puede transferirse, si A es amigo de B, y B es
amigo de C, esto no implica que A sea amigo de C la amistad no puede heredarse. Si A es amigo de B, y C es una
clase derivada de B, A no es amigo de C la amistad no es simétrica. Si A es amigo de B, B no tiene por
qué ser amigo de A 78
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Sistema de protección
Ejemplo: funciones amigas externas
79
class A { public:
A(int i=0) : a(i) {}
private: int a; friend void Ver(A); // "Ver" es amiga de la clase A
}; void Ver(A Xa) {
// La función Ver puede acceder a miembros privados // de la clase A, ya que ha sido declarada "amiga" de A cout << Xa.a << endl;
}
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Sistema de protección
Ejemplo: funciones amigas en otras clases
80
class A; // Declaración previa (forward) class B { public:
B(int i=0) : b(i) {} void Ver() { cout << b << endl; } bool EsMayor(A Xa); // Compara b con a
private: int b;
}; class A { public:
A(int i=0) : a(i) {} void Ver() { cout << a << endl; }
private: // Función amiga tiene acceso a miembros privados de la clase A friend bool B::EsMayor(A Xa); int a;
};
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Sistema de protección
Ejemplo: clases amigas
81
/* Clase para elemento de lista enlazada */ class Elemento { public:
Elemento(int t); int Tipo() { return tipo;}
private: int tipo; Elemento *sig; // siguiente elemento friend class Lista; // amistad con lista
}; /* Clase para lista enlazada de números*/ class Lista {
. . . }
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Modificadores de miembros
Funciones miembro inline El código generado para esa función cuando el programa se
compila, se inserta en todos los punto donde se invoca a la función, en lugar de hacerlo en otro lugar y hacer llamadas
Hay dos maneras de declarar una función como inline: Las funciones que se definen dentro de la declaración de la clase
son inline implícitamente La otra forma es hacerlo explícitamente
82
class Ejemplo { public:
Ejemplo(int a = 0); private:
int A; }; inline Ejemplo::Ejemplo(int a) : A(a) {}
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Modificadores de miembros
Funciones miembro const Cuando una función miembro no modifique el valor de
ningún dato de la clase, podemos y debemos declararla como constante
si la función intenta modificar el objeto el compilador generará un error
83
class Ejemplo2 { public:
Ejemplo2(int a = 0) : A(a) {} void Modifica(int a) { A = a; } // Error si se declara constante int Lee() const { return A; }
private: int A;
};
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Modificadores de miembros
Otros usos de const valores de retorno constantes de las funciones paso de parámetros constantes a funciones
84
const Vector Vector::operator+( const Vector &other ) const { Vector result; result.x = this->x + other.x; result.y = this->y + other.y; result.z = this->z + other.z; return result;
}
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Modificadores de miembros
Miembros static de una clase Son miembros que no dependen de un objeto o instancia
concreto sino que funcionan a nivel de clase En el caso de los atributos static sólo existirá una copia que
compartirán todos los objetos de la misma clase Es necesario inicializar los datos estáticos de una clase
Las funciones static no pueden acceder a los miembros de los objetos, sólo pueden acceder a los datos miembro de la clase que sean static
85
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Modificadores de miembros
Ejemplo:
86
class Singleton { public: static Singleton* Instance(); private: Singleton(); Singleton(const Singleton &); Singleton &operator= (const Singleton &); static Singleton* pinstance; }; Singleton* Singleton::pinstance = NULL;// Inicializa el miembro static Singleton* Singleton::Instance () {
if (pinstance == NULL) // ¿Es la primera llamada? pinstance = new Singleton; // Creamos la instancia
return pinstance; } Singleton *obj = Singleton::Instance();
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Example 07 – GLUT orientado a objetos
87
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Herencia
Nos permite crear nuevas clases a partir de clases existentes, conservando las propiedades de la clase original y añadiendo otras nuevas
La nueva clase obtenida se conoce como clase derivada, y las clases a partir de las cuales se deriva, clases base cada clase derivada puede usarse como clase base para
obtener una nueva clase derivada y cada clase derivada puede serlo de una o más clases base
88
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Herencia
Esto nos va a permitir crear jerarquías de clases tan complejas como nos sea necesario
89
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Herencia
Un ejemplo muy común es de las personas todas las personas tienen propiedades comunes, nombre,
fecha de nacimiento, género, estado civil, etc. dividimos a todas las personas en dos grandes clases:
empleados y estudiantes los ingresos por nómina son exclusivos de los empleados la nota media del curso es exclusiva de los estudiantes ahora podemos clasificar a los empleados en ejecutivos y
comerciales ….
90
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Herencia
Ahora podemos ver las ventajas de disponer de una jerarquía completa de clases Cada vez que creemos un objeto de cualquier tipo
derivado este tendrá las propiedades de todos sus tipos base
Siempre podremos crear nuevas clases para resolver nuevas situaciones
Podemos aplicar procedimientos genéricos a una clase en concreto sin tener en cuenta que tipo de subclase es
91
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Herencia
Ejemplo:
92
// Clase base Persona: class Persona { public:
Persona(char *n, int e); const char *LeerNombre(char *n) const; int LeerEdad() const; void CambiarNombre(const char *n); void CambiarEdad(int e);
protected: char nombre[40]; int edad;
}; // Clase derivada Empleado: class Empleado : public Persona { public:
Empleado(char *n, int e, float s); float LeerSalario() const; void CambiarSalario(const float s);
protected: float salarioAnual;
};
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Herencia
Para cada clase base podemos definir dos tipos de acceso, public o private. Si no se especifica ninguno de los dos, por defecto se asume que es private public: los miembros heredados de la clase base conservan el
tipo de acceso con que fueron declarados en ella private: todos los miembros heredados de la clase base pasan a
ser miembros privados en la clase derivada
Usar el acceso protected nos permite que los datos sean inaccesibles desde el exterior de las clases, pero a la vez, permite que sean accesibles desde las clases derivadas
93
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Herencia
Constructores en clases derivadas Cuando se crea un objeto de una clase derivada, primero
se invoca al constructor de la clase base y a continuación al constructor de la clase derivada Si el constructor base no tiene parámetros la llamada se
realiza de forma automática Si el constructor base necesita parámetros, tenemos que
encargarnos nosotros de llamar al constructor base
94
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Herencia
Ejemplo:
95
class ClaseA { public:
ClaseA(int a) : datoA(a) { cout << "Constructor de A" << endl; } int LeerA() const { return datoA; }
protected: int datoA;
}; class ClaseB : public ClaseA { public:
ClaseB(int a, int b) : ClaseA(a), datoB(b) { (1) cout << "Constructor de B" << endl; } int LeerB() const { return datoB; }
protected: int datoB;
};
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Herencia
Destructores en clases derivadas Cuando se destruye un objeto de una clase derivada,
primero se invoca al destructor de la clase derivada, si existen objetos miembro a continuación se invoca a sus destructores y finalmente al destructor de la clase base
96
class ClaseB : public ClaseA { public:
ClaseB() : datoB(20) { cout << "Constructor de B" << endl; } ~ClaseB() { cout << "Destructor de B" << endl; } int LeerB() const { return datoB; }
protected: int datoB;
};
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Polimorfismo
En una clase derivada se puede definir una función que ya existía en la clase base, esto se conoce como "overriding", o superposición de una función La definición de la función en la clase derivada oculta la
definición previa en la clase base Podemos acceder a la función de la clase base mediante
una sintaxis un tanto especial
Superposición Cuando se superpone una función, se ocultan todas las
funciones con el mismo nombre en la clase base 97
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Polimorfismo
Ejemplo:
98
class ClaseA { public:
ClaseA() : datoA(10) {} int LeerA() const { return datoA; } void Mostrar() { cout << "a = " << datoA << endl; }
protected: int datoA;
}; class ClaseB : public ClaseA { public:
ClaseB() : datoB(20) {} int LeerB() const { return datoB; } void Mostrar() { cout << "a = " << datoA << ", b = “ << datoB << endl; }
protected: int datoB;
}; ClaseB objeto; objeto.Mostrar(); objeto.ClaseA::Mostrar();
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
C++ nos permite acceder a objetos de una clase derivada usando un puntero a la clase base
Por supuesto, sólo podremos acceder a datos y funciones que existan en la clase base, los datos y funciones propias de los objetos de clases derivadas serán inaccesibles
Con lo que hemos visto hasta ahora, si accedemos a objetos de una clase derivada usando un puntero a la clase base, se ejecuta el código de la clase base
99
Polimorfismo
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Polimorfismo
Ejemplo:
100
class Persona { public:
Persona(char *n) { strcpy(nombre, n); } void VerNombre() { cout << nombre << endl; }
protected: char nombre[30];
}; class Empleado : public Persona { public:
Empleado(char *n) : Persona(n) {} void VerNombre() { cout << "Emp: " << nombre << endl; }
}; class Estudiante : public Persona { public:
Estudiante(char *n) : Persona(n) {} void VerNombre() { cout << "Est: " << nombre << endl; }
}; Persona *Pepito = new Estudiante("Jose"); Persona *Carlos = new Empleado("Carlos");
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Polimorfismo
Sería mucho más interesante que cuando se invoque a una función que se superpone en la clase derivada, se llame a ésta última función, la de la clase derivada
Esto se consigue mediante el uso de funciones virtuales cuando en una clase declaramos una función como virtual,
y la superponemos en alguna clase derivada, al invocarla usando un puntero de la clase base, se ejecutará la versión de la clase derivada
101
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Polimorfismo
Ejemplo:
102
class Persona { public:
Persona(char *n) { strcpy(nombre, n); } virtual void VerNombre() { cout << nombre << endl; }
protected: char nombre[30];
}; class Empleado : public Persona { public:
Empleado(char *n) : Persona(n) {} void VerNombre() { cout << "Emp: " << nombre << endl; }
}; class Estudiante : public Persona { public:
Estudiante(char *n) : Persona(n) {} void VerNombre() { cout << "Est: " << nombre << endl; }
}; Persona *Pepito = new Estudiante("Jose"); Persona *Carlos = new Empleado("Carlos");
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Polimorfismo
También funciona con referencias
Una vez que una función es declarada como virtual, lo seguirá siendo en las clases derivadas, es decir, la propiedad virtual se hereda
103
Estudiante Pepito("Jose"); Empleado Carlos("Carlos"); Persona &rPepito = Pepito; // Referencia como Persona Persona &rCarlos = Carlos; // Referencia como Persona rCarlos.VerNombre(); rPepito.VerNombre();
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Polimorfismo
1. Supongamos que tenemos una estructura de clases en la que en alguna de las clases derivadas exista un destructor…
2. si destruimos un objeto referenciado mediante un puntero a la clase base, y el destructor no es virtual, estaremos llamando al destructor de la clase base…
3. ¡Esto puede ser desastroso!
Destructores virtuales debemos respetar siempre ésta regla: si en una clase
existen funciones virtuales, el destructor debe ser virtual
104
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Polimorfismo
1. accedemos a un objeto de una clase derivada usando una referencia a la clase base …
2. llamamos al constructor copia para crear una nueva copia de esa clase…
3. ¡Estamos llamando al constructor copia de la clase base para copiar una clase derivada!
Constructores virtuales Los constructores no pueden ser virtuales Si un constructor llama a una función virtual, ésta será siempre
la de la clase base (la clase derivada aún no se ha creado) Para solucionar este inconveniente se suele crear una función
virtual "clonar" en la clase base que se superpondrá para cada clase derivada
105
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Polimorfismo
Ejemplo:
106
class Persona { public:
Persona(char *n) { strcpy(nombre, n); } Persona(const Persona &p); virtual Persona* Clonar() { return new Persona(*this); }
protected: char nombre[30];
}; class Empleado : public Persona { public:
Empleado(char *n) : Persona(n) {} Empleado(const Empleado &e); virtual Persona* Clonar() { return new Empleado(*this); }
}; class Estudiante : public Persona { public:
Estudiante(char *n) : Persona(n) {} Estudiante(const Estudiante &e); virtual Persona* Clonar() { return new Estudiante(*this); }
};
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Clases abstractas
Funciones virtuales puras Una función virtual pura es aquella que no necesita ser
definida El modo de declarar una función virtual pura es
asignándole el valor cero
107
class Persona { public:
Persona(char *n) { strcpy(nombre, n); } virtual void Mostrar() = 0;
protected: char nombre[30];
};
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Clases abstractas
Clase abstracta Una clase abstracta es aquella que posee al menos una
función virtual pura No es posible crear objetos de una clase abstracta, estas
clases sólo se usan como clases base para la declaración Las funciones virtuales puras serán aquellas que siempre
se definirán en las clases derivadas, de modo que no se necesita implementación base
Siempre hay que definir todas las funciones virtuales de una clase abstracta en sus clases derivadas, no hacerlo así implica que la nueva clase derivada será también abstracta
108
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Clases abstractas
Ejemplo:
109
class Persona { public:
Persona(char *n) { strcpy(nombre, n); } virtual void Mostrar() = 0;
protected: char nombre[30];
}; class Empleado : public Persona { public:
Empleado(char *n, int s) : Persona(n), salario(s) {} void Mostrar() { cout << "Empleado: " << nombre << ", Salario: " << salario << endl; }
protected: int salario;
}; Persona *Jose = new Persona(“Jose”); // ERROR Persona *Pepito = new Empleado(“Pepito", 1000);
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Interfaces
Las interfaces surgen como una evolución de la POO Programación orientada a componentes
ante la necesidad de reutilizar y agrupar las distintas funcionalidades de un objeto en subconjuntos mas manejables
Definen un cierto comportamiento o cualidades
En términos de C++ es una clase abstracta con métodos virtuales puros
La derivación múltiple nos permitirá luego agrupar varias de esas funcionalidades dentro de una clase nuestro objeto ira cobrando forma a partir de la herencia de
distintas interfaces o cualidades
110
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Interfaces
Ejemplo:
111
/* Interface para objetos dibujables */ class IDrawable { public:
Virtual bool IsVisible()=0; virtual void Draw()=0;
}; /* Interface para objetos actualizables */ class IUpdateable { public:
virtual void Update(float dt)=0; }; Class Actor : public IUpdateable, public IDrawable { Public:
bool IsVisible() { return true } void Draw() { ... } void Update (float dt) { ... }
}
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Derivación múltiple
C++ permite crear clases derivadas a partir de varias clases base Los objetos heredarán los datos y funciones de todas las
clases base Al construir el nuevo objeto, si es necesario debemos
llamar a los constructores de todas las clases base
112
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Derivación múltiple
Ejemplo:
113
class ClaseA { public:
ClaseA(int va = 10) : valorA(va) {} int LeerValor() const { return valorA; }
protected: int valorA;
}; class ClaseB { Public:
ClaseB(int vb = 20) : valorB(vb) {} int LeerValor() const { return valorB; }
protected: int valorB;
}; class ClaseC : public ClaseA, public ClaseB { public:
ClaseC(int va, int vb) : ClaseA(va), ClaseB(vb) {}; int LeerValorA() const { return ClaseA::LeerValor(); } int LeerValorB() const { return ClaseB::LeerValor(); }
};
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Derivación múltiple
Problema: Supongamos que tenemos una estructura de clases
La ClaseD heredará dos veces los datos y funciones de la ClaseA, con la consiguiente ambigüedad a la hora de acceder a datos o funciones heredadas de ClaseA
114
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Derivación múltiple
Para solucionar esto se usan las clases virtuales
Desde el punto de vista de la ClaseB o ClaseC, no hay
ninguna diferencia entre ésta declaración y la que hemos usado hasta ahora
115
class ClaseB : virtual public ClaseA {}; class ClaseC : virtual public ClaseA {}; class ClaseD : public ClaseB, public ClaseC {};
Sin embargo, ahora la ClaseD sólo heredará una vez la ClaseA
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Example 08 –Shapes
Jugando con la herencia y polimorfismo
116
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Plantillas
117
class TablaInt { public:
TablaInt(int nElem); ~TablaInt(); int& operator[](int indice) { return pInt[indice]; } ...
private: int *pInt; int nElementos;
}; // Definición: TablaInt::TablaInt(int nElem) : nElementos(nElem) {
pInt = new int[nElementos]; } TablaInt::~TablaInt() {
delete[] pInt; }
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Plantillas
Según va aumentando la complejidad de nuestros programas descubrimos que tenemos que repetir una y otra vez las mismas estructuras A menudo tendremos que implementar arrays dinámicos
para diferentes tipos de objetos, o listas dinámicas, pilas, colas, árboles, etc.
El código es similar siempre, pero estamos obligados a rescribir ciertas funciones que dependen del tipo o de la clase del objeto que se almacena
Las plantillas (templates) nos permiten parametrizar estas clases para adaptarlas a cualquier tipo de dato
118
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Plantillas
Ejemplo: plantillas de clases
119
template <class T> class Tabla { public:
Tabla(int nElem); ~Tabla(); T& operator[](int indice) { return pT[indice]; }
private: T *pT; int nElementos;
}; // Definición: template <class T> Tabla<T>::Tabla(int nElem) : nElementos(nElem) {
pT = new T[nElementos]; } template <class T> Tabla<T>::~Tabla() {
delete[] pT; }
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Plantillas
Ya sólo nos queda saber cómo declarar tablas del tipo que queramos
120
Tabla<int> tablaInt(32); // Tabla de 32 enteros Tabla<float> tablaFloat(12); // Tabla de 12 floats Tabla<bool> tablaBool(10); // Tabla de 10 bools
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Plantillas
Ejemplo: plantillas de funciones
De esta forma tendremos definida la función max para
cualquier tipo de dato que tenga implementado correctamente el operador “mayor que”
121
template <class T> T max(T x, T y) {
return (x > y) ? x : y; };
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Plantillas
Es posible crear funciones que admitan parámetros que sean una plantilla
Hay dos modos de pasar las plantillas: se puede pasar una instancia determinada de la plantilla la plantilla genérica
122
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Plantillas
Ejemplo: paso de una instancia determinada
123
void Incrementa(Tabla<int> &t); ... void Incrementa(Tabla<int> &t) {
for(int i = 0; i < t.NElementos(); i++) t[i]++;
} Tabla<int> TablaInt(5); Tabla<char> TablaChar(20); Incrementa(TablaInt); Incrementa(TablaChar); // ERROR
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Plantillas
Ejemplo: paso de la plantilla genérica
124
template<class T> void Mostrar(Tabla<T> &t); ... template<class T> void Mostrar(Tabla<T> &t) { // (4) for(int i = 0; i < t.NElementos(); i++) cout << t[i] << endl; } Tabla<int> TablaInt(5); Tabla<char> TablaChar(20); Mostrar(TablaInt); Mostrar(TablaCadena);
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Plantillas
Amigos de plantillas
125
template <class T> class Tabla {
... friend void Mostrar<>(Tabla<T>&); ...
};
template<class T> class Tabla {
... friend void Mostrar<>(Tabla<int>&); ...
};
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
El ANSI de C++ define ciertas librerías de plantillas conocidas como STL (Standard Template Library)
Contiene muchas definiciones de plantillas para crear contenedores como listas, colas, pilas, árboles, tablas HASH, mapas, etc.
Además proporciona algoritmos que permiten manipular fácilmente estos contenedores
La STL introduce igualmente el concepto de iterador que permite recorrer fácilmente un contenedor sin tener en cuenta la manera en que ha sido implementado
126
Librería estándar de C++
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Example 09 - Plantilla de una pila
127
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Excepciones
C++ proporciona un mecanismo más potente para detectar errores de ejecución: las excepciones
Si uno de esos errores se produce y no implementamos el manejo de excepciones, el programa sencillamente terminará abruptamente
Para ello disponemos de tres palabras reservadas extra: try, catch y throw
128
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Excepciones
Ejemplo: manejo de excepciones
129
#include <iostream> using namespace std; int main() {
int *x; int y = 100000000; try {
x = new int[y]; x[0] = 10; cout << "Puntero: " << (void *) x << endl; delete[] x;
} catch(std::bad_alloc&) {
cout << "Memoria insuficiente" << endl; } cin.get(); return 0;
}
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Excepciones
Manejo de excepciones La manipulación de excepciones consiste en transferir la
ejecución del programa desde el punto donde se produce la excepción a un manipulador que coincida con el motivo de la excepción
Un manipulador consiste en un bloque "try", donde se incluye el código que puede producir la excepción
A continuación encontraremos uno o varios bloques "catch", y entre paréntesis una referencia o un objeto. Estos bloques contienen el código necesario para tratar una excepción de un tipo concreto En el caso del operador "new", si se produce una excepción,
se hace un "throw" de un objeto de la clase "std::bad_alloc"
130
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Excepciones
Captura de excepciones Una excepción se puede producir por un "throw" que se
encuentre dentro del bloque "try" asociado, o en una de las funciones llamadas desde él
Cuando se produce una excepción se busca un manipulador apropiado en el rango del "try" actual
Si no se encuentra se retrocede al anterior, de modo recursivo, hasta encontrarlo
Cuando se encuentra se destruyen todos los objetos locales en todos los niveles por los que hemos pasado
131
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Excepciones
Ejemplo: propagación de excepciones
132
int main() { try {
try { try {
throw 'x'; // valor de tipo char } catch(int i) {} catch(float k) {}
} catch(unsigned int x) {}
} catch(char c) {
cout << "El valor de c es: " << c << endl; } cin.get(); return 0;
}
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Excepciones
Si no se encontrase ningún "catch" adecuado, se abandona el programa, del mismo modo que si se produce una excepción y no hemos hecho ningún tipo de manipulación de excepciones
Para evitar eso existe un "catch" general, que captura cualquier "throw" para el que no exista un "catch"
133
catch(...) { cout << "Excepción imprevista" << endl;
}
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Excepciones
La clase exception Existe una clase base "exception" de la que podemos
heredar nuestras propias clases derivadas para pasar objetos a los manipuladores
Aplicando polimorfismo necesitamos un único "catch" para procesar todas las posibles excepciones
134
class exception { public:
exception() throw() { } virtual ~exception() throw(); virtual const char* what() const throw();
};
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Excepciones
Ejemplo: custom exception
135
class customException : public exception { public:
customException(int mot) : exception(), motivo(mot) {} const char* what() const throw();
private: int motivo;
}; const char* customException::what() const throw() {
switch(motivo) { case 1:
return "Fichero de origen no existe"; case 2:
return "No es posible abrir el fichero de salida"; } return "Error inesperado";
}
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Excepciones
Orden en la captura de excepciones Cuando se derivan clases desde la clase base "exception"
hay que tener cuidado en el orden en que las capturamos Debido que se aplica polimorfismo, cualquier objeto de la
jerarquía se ajustará al catch que tenga por argumento un objeto o referencia de la clase base
136
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Excepciones
Ejemplo: orden en captura excepciones
137
class Excep2 : public exception {} class Excep3 :public Excep2 {} ... try { // Nuestro código } catch(Excep2&) { // tratamiento } catch(Excep3&) { // tratamiento } catch(exception&) { // tratamiento } catch(...) { // tratamiento }
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Excepciones
Especificaciones de excepciones Se puede añadir una especificación de las posibles
excepciones que puede producir una función De este modo indicamos que la función sólo puede hacer
un "throw" de uno de los tipos especificados en la lista El compilador no verifica si realmente es así, sólo se
verifica durante la ejecución, de modo que si se produce una excepción no permitida, el programa termina
138
int Compara(int, int) throw(); int CrearArray(int) throw(std::bad_alloc); int MiFuncion(char *) throw(std::bad_alloc, ExDivCero);
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Excepciones
Excepciones en destructores Está desaconsejado que los destructores puedan producir
excepciones Los destructores pueden ser invocados automáticamente
cuando se procesa una excepción, y si durante ese proceso se produce de nuevo una excepción, el programa terminará inmediatamente
La mejor solución es procesar las excepciones dentro del destructor si es necesario
139
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Excepciones
Ejemplo: excepciones en destructores
140
Miclase::~MiClase() throw () { try { // Necesitamos copiar un fichero cuando se // destruya un objeto de esta clase, pero // CopiaFichero puede generar una excepción
CopiaFichero("actual.log", "viejo.log"); } catch(CopiaEx&) {
cout << "No se pudo copiar el fichero 'actual.log‘” << endl;
} }
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Excepciones
Relanzar una excepción Podemos lanzar una excepción a través de los siguientes
niveles, aunque la hayamos capturado A eso se le llama relanzarla, y para ello se usa "throw;", sin
argumentos
141
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Excepciones
Ejemplo: relanzar una excepción
142
try { // Programa Programa();
} catch(int x) {
cout << "Excepción relanzada capturada." << endl; cout << "error: " << x << endl;
} void Programa() {
try { // Operaciones... throw 10;
} catch(int x) {
// Relanzar, no nos interesa manejar aquí throw;
} }
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Operadores de cambio de tipo en C++
143
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Castings en C++
Hasta ahora hemos usado sólo el casting que existe en C, pero su uso está desaconsejado
Se recomienda usar uno de los nuevos operadores de C++ diseñados para realizar esta tarea
C++ dispone de cuatro operadores para realizar castings: Operador static_cast<> Operador const_cast<> Operador reinterpret_cast<> Operador dynamic_cast<>
144
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Castings en C++
Operador static_cast<> Este operador se usa para realizar conversiones de tipo
que de otro modo haría el compilador automáticamente por ejemplo, convertir un puntero a un objeto de una clase
derivada a un puntero a una clase base pública Otro ejemplo, en lugar de usar el operador de conversión
de forma implícita, podemos usarlo mediante el operador static_cast
Este operador se usa con objeto de aclarar el código
145
pBase = static_cast<Base *> (pDerivada); Tiempo Ahora(12,24); int minutos = static_cast<int> (Ahora);
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Castings en C++
Operador const_cast<> Se usa para eliminar o añadir los modificadores const y
volatile de una expresión La conversión tiene que ser del mismo tipo, salvo por los
modificadores const o volatile que tengan que aparecer o desaparecer
146
const int x = 10; int *x_var; x_var = const_cast<int*> (&x); // Válido // x_var = &x; // Ilegal, el compilador da error *x_var = 14; // Indefinido
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Castings en C++
Operador reinterpret_cast<> Se usa para hacer cambios de tipo a nivel de bits, es decir,
el valor de la expresión a convertir se interpreta como si fuese un objeto del tipo deseado
Este tipo de conversión es peligrosa
147
struct tipoRegistro { char nombre[32]; int edad; float altura;
}; ifstream fentrada("prueba.dat", ios::in | ios::binary); fentrada.read(reinterpret_cast<char *> &pepe2, sizeof(tipoRegistro)); fentrada.close();
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Castings en C++
Operador dynamic_cast<> Este operador sólo puede usarse con objetos polimórficos,
cualquier intento de aplicarlo a objetos de tipos fundamentales o agregados o de clases no polimórficas dará como resultado un error
Lo que el programa intentará hacer, durante la ejecución, es obtener un puntero o una referencia a un objeto de cierta una base en forma de clase derivada pero puede que se consiga, o puede que no
148
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Castings en C++
Operador dynamic_cast<> Con punteros:
149
void VerSueldo(Persona *p) { if(Empleado *pEmp = dynamic_cast<Empleado *> (p))
pEmp->VerSueldo(); else
cout << "No tiene salario." << endl; }
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Castings en C++
Operador dynamic_cast<> Con referencias:
Al aplicar el operador con referencias hay que tener más cuidado, ¿Qué pasará si el casting falla?
150
void VerSueldo(Persona &p) { Empleado& rEmp = dynamic_cast<Empleado &> p; ...
}
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Ficheros en C++
151
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Ficheros en C++
Usar streams facilita mucho el acceso a ficheros en disco
veremos que una vez que creemos un stream para un fichero, podremos trabajar con él igual que lo hacemos con cin o cout
Mediante las clases ofstream, ifstream y fstream tendremos acceso a gran cantidad de funciones que nos van a facilitar la tarea
152
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Ficheros en C++
153
#include <iostream> #include <fstream> using namespace std; int main() {
char cadena[128]; // Crea un fichero de salida ofstream fs("nombre.txt"); fs << "Hola, mundo" << endl; fs.close(); // Abre un fichero de entrada ifstream fe("nombre.txt"); // Leeremos mediante getline, si lo hiciéramos mediante el operador >> sólo leeríamos parte de la cadena: fe.getline(cadena, 128); cout << cadena << endl; return 0;
}
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Ficheros en C++
Muchos sistemas operativos distinguen entre ficheros de texto y ficheros binarios En general, usaremos ficheros de texto para almacenar
información que pueda o deba ser manipulada con un editor de texto
Ficheros binarios para todo lo demás Un fichero binario permite almacenar estructuras completas,
en las que se mezclen datos de cadenas con datos numéricos
154
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Ficheros en C++
155
struct tipoRegistro { char nombre[32]; int edad; float altura; }; int main() {
tipoRegistro pepe, pepe2; ofstream fsalida("prueba.dat", ios::out | ios::binary); fsalida.write(reinterpret_cast<char *> &pepe, sizeof(tipoRegistro)); fsalida.close(); ifstream fentrada("prueba.dat", ios::in | ios::binary); fentrada.read(reinterpret_cast<char *> &pepe2, sizeof(tipoRegistro)); fentrada.close(); return 0;
}
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Ficheros en C++
Ficheros de acceso aleatorio Otra característica importante de los ficheros es la
posibilidad de trabajar con ellos haciendo acceso aleatorio, es decir, poder hacer lecturas o escrituras en cualquier punto del fichero
Para eso disponemos de las funciones seekp y seekg, que permiten cambiar la posición del fichero en la que se hará la siguiente escritura o lectura
156
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Ficheros en C++
157
char cad[20]; char mes[][20] = {"Enero", "Febrero", "Marzo", ...}; // Acceso aleatorio for(i = 11; i >= 0; i--) {
fentrada.seekg(20 * i, ios::beg); fentrada.read(cad, 20); cout << cad << endl;
} /* Calcular el número de elementos almacenados en un fichero: */ // ir al final del fichero fentrada.seekg(0, ios::end); // leer la posición actual pos = fentrada.tellg(); // El número de registros es el tamaño en bytes dividido entre el tamaño del registro cout << “Número de registros: " << pos/20 << endl;
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Ficheros en C++
Sobrecarga de operadores << y >> Una de las principales ventajas de trabajar con streams es
que nos permiten sobrecargar los operadores << y >> para realizar salidas y entradas de nuestros propios tipos de datos
158
ostream& operator<<(ostream &os, Registro& reg) { os << "Nombre: " << reg.LeeNombre() <<"\nEdad: " << reg.LeeEdad() << "\nTelefono: " << reg.LeeTelefono(); return os;
}
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Ficheros en C++
Example 10 - Importación de modelos 3D
Lectura de ficheros de texto mediante streams
159
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Libros recomendados
160
P R O G R A M A C I Ó N
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA
Curso 0: Programación orientada a objetos (POO)
Iván Alduán ([email protected])
(despacho 143 Departamental II, Campus Móstoles)
161