SlideShare una empresa de Scribd logo
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Programaci´on en C++ para Ciencia e
Ingenier´ıa
Mario Storti, Lisandro Dalc´ın, Rodrigo Paz
http://www.cimec.org.ar/prog
Facultad de Ingenier´ıa y Ciencias H´ıdricas
Universidad Nacional del Litoral http://www.unl.edu.ar
Centro de Investigaci´on de M´etodos Computacionales - CIMEC
INTEC, (CONICET-UNL), http://www.cimec.org.ar
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 1
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Autores
• Mario Storti <mario.storti@gmail.>
• Lisandro Dalc´ın, <dalcinl@gmail.com>
• Rodrigo Paz, <rodrigo.r.paz@gmail.com>
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 2
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Contents
• slide 11.....Elementos b´asicos de programaci´on
slide 13.....Compilaci´on vs. int´erpretes
slide 14.....El proceso de compilaci´on
slide 16.....El preprocesador CPP
slide 19.....Chequeo de tipos
slide 20.....Compilaci´on por separado
slide 22.....Declaraciones y definiciones
slide 24.....Definiciones y declaraciones de variables
slide 26.....Incluyendo headers
slide 29.....Usando librer´ıas
slide 30.....Formato de include para C++
slide 31.....Un primer programa en C++
slide 32.....Namespaces
slide 35.....Estructura de un programa
slide 37.....Hello world
slide 38.....Concatenaci´on de arreglos de caracters
slide 39.....Entrada de datos
slide 40.....Llamando a otros programas
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 3
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
slide 41.....Strings de C
slide 42.....Strings de C++
slide 44.....Escribir y leer de archivos
slide 46.....La clase vector
slide 49.....Ejercicios
• slide 50.....El C en C++
slide 51.....Funciones
slide 52.....Valores de retorno
slide 54.....Usando la librer´ıa est´andar de C
slide 55.....Control de ejecuci´on. True and False
slide 57.....If-else
slide 61.....while
slide 64.....do-while
slide 65.....Lazo for
slide 66.....Break and continue
slide 68.....La sentencia switch
slide 70.....goto
slide 72.....Recursion
slide 74.....Operadores
slide 75.....Operadores de auto incremento
slide 77.....Tipos de datos
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 4
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
slide 80.....Especificadores
slide 84.....Punteros
slide 94.....Referencias
slide 96.....Punteros a void
slide 98.....Scope de las variables
slide 100.....Definiendo variables on-the-fly
slide 104.....Variables locales
slide 108.....Punteros a variables locales
slide 109.....Variables est´aticas
slide 111.....Constantes
slide 112.....Operadores. Asignaci´on
slide 113.....Operadores matem´aticos
slide 114.....Operadores relacionales
slide 115.....Operadores l´ogicos
slide 116.....El operador hook
slide 117.....Errores comunes con los operadores
slide 118.....Operadores de cast
slide 119.....Operador sizeof
slide 120.....typedef: Aliases de tipos
slide 121.....Estructuras
slide 125.....Arrow operator
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 5
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
slide 126.....Enum’s
slide 129.....Arreglos de estructuras
slide 130.....Punteros y arreglos
slide 132.....Arreglos de punteros
slide 136.....Aritm´etica de punteros
slide 138.....Tama˜nos de estructuras
• slide 139.....Programaci´on Orientada a Objetos
slide 140.....Abstracci´on de datos
slide 150.....POO b´asica
slide 160.....Inclusion de headers
slide 164.....Estructuras enlazadas
slide 172.....M´as sobre scoping
slide 173.....Tipos Abstractos de Datos (ADT)
slide 174.....Ocultando la implementaci´on
slide 176.....Control de acceso a los miembros
slide 180.....Amistad (Friendship)
slide 183.....Anidamiento (nesting) y amistad
slide 184.....Object layout
slide 185.....Clases
slide 189.....Ocultando totalmente la implementaci´on
slide 191.....Inicializaci´on y cleanup
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 6
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
slide 193.....El constructor
slide 194.....El destructor
slide 197.....Eliminaci´on del bloque de definici´on
slide 199.....Clase stash con ctor/dtor
slide 203.....Stack con ctor/dtor
slide 206.....Initializaci´on de agregados
slide 207.....Inicializaci´on de estructuras
slide 208.....Sobrecarga de funciones
slide 212.....Argumentos por default
slide 213.....Constantes
slide 216.....Punteros a arreglos constantes de caracteres
slide 217.....Const en argumentos de funciones
slide 218.....Const en clases
slide 219.....Objetos const y funciones de la clase
• slide 221.....Chapter 5
slide 222.....Funciones inline
slide 226.....Especificaciones de linkedicion
slide 228.....Referencias en C++
slide 234.....Reglas para las referencias
slide 236.....Paso por referencia y por copia
slide 237.....El constructor por copia
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 7
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
slide 238.....Sobrecarga de operadores
slide 243.....Sobrecarga de operadores unarios
slide 251.....Sobrecarga de operadores binarios
• slide 273.....Chapter
slide 274.....Otros operadores que se pueden sobrecargar
slide 275.....Creaci´on din´amica de objetos
slide 276.....Uso de la memoria din´amica en C
slide 277.....Uso de la memoria din´amica en C++
slide 279.....Porqu´e usar new y no arreglos
slide 280.....Memory exhaust
slide 281.....Composici´on
slide 283.....Composici´on y la cadena de inicializaci´on
slide 284.....Herencia
slide 287.....Redefinici´on de m´etodos
slide 289.....Herencia protegida
slide 291.....Upcasting
slide 292.....Polimorfismo
slide 294.....Ejemplo polimorfismo. Integral 1D/2D/3D
slide 298.....Clase que calcula integral 1D
slide 300.....Integral 2D. Versi´on cruda
slide 315.....Integral 2D. Versi´on mejorada
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 8
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
slide 318.....Integral 3D
slide 321.....Integral 1D/2D/3D. User code
slide 323.....Polimorfismo: ej. suma de los elementos de un vector
slide ??.....Ejemplo clase vector sparse
• slide 326.....Contenedores de la librer´ıa STL
slide 328.....La librer´ıa STL
slide 328.....La clase vector
slide 333.....Algoritmos in-place
slide 335.....La clase list
slide 338.....La clase set
slide 342.....La clase map
slide 345.....Algoritmos
slide 347.....Programaci´on funcional
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 9
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Dictado
• Docentes de la c´atedra:
Mario Storti <mario.storti@gmail.>
Lisandro Dalc´ın, <dalcinl@gmail.com>
Rodrigo Paz, <rodrigo.r.paz@gmail.com>
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 10
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Elementos b´asicos de
programaci´on
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 11
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
I KNOW C++!
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 12
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Compilaci´on vs. int´erpretes
• Algunos lenguajes de programaci´on tienen un int´erprete, por ejemplo
Matlab/Octave, Python, Perl, Lisp/Scheme. En un int´erprete el usuario va
emitiendo comandos que son interpretados por el int´erprete y va
devolviendo un resultado.
• Por contraposici´on, los lenguajes compilados el usuario escribe un
archivo con l´ıneas de c´odigo, el cu´al es procesado por un compilador, que
genera c´odigo de m´aquina, el cual es ejecutado directamente por el
procesador.
• Ventajas de la compilaci´on: el c´odigo suele ser m´as r´apido, y m´as
compacto.
• Desventajas: el paso de c´odigo a ejecutarlo es inmediato, no hay pasos
intermedios. Usualmente los int´erpretes permiten escribir tareas que se
repiten com´unmente en archivos de texto (scripts). El usuario puede
adem´as mezclar estas funciones con comandos directamente en el
int´erprete. Tambi´en con los int´erprete es m´as f´acil debuggear.
• C++ es un lenguaje compilado.
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 13
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
El proceso de compilaci´on
• El caso m´as simple es cuando todo el c´odigo del programa est´a en un
s´olo archivo fuente:
1 $$ g++ -o prog prog.cpp
Genera un archivo ejecutable prog.
• Si el programa es muy grande conviene dividirlo en varias partes, en ese
caso
1 $$ g++ -o prog prog1.cpp prog2.cpp
• Esto requiere recompilar cada vez todos los *.cpp, si son muchos
conviene hacer
1 $$ g++ -o prog1.o -c prog1.cpp
2 $$ g++ -o prog2.o -c prog2.cpp
3 $$ g++ -o prog prog1.o prog2.o
Los archivos .o son objeto, contienen c´odigo de m´aquina. (No tiene
relaci´on con la Programaci´on Orientada a Objetos).
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 14
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
El proceso de compilaci´on (cont.)
• Si solo se modifica uno de los archivos (prog1.cpp), entonces s´olo hace
falta recompilar ese.
1 $$ g++ -o prog1.o -c prog1.cpp
2 $$ g++ -o prog prog1.o prog2.o
• Para mejor organizaci´on, si hay muchos *.o conviene ponerlos en una
librer´ıa
1 $$ g++ -o prog1.o -c prog1.cpp
2 $$ g++ -o prog2.o -c prog2.cpp
3 $$ g++ -o prog3.o -c prog3.cpp
4 $$ ar r libprog.a prog1.o prog2.o prog3.o
5 $$ g++ -o prog main.cpp libprog.a
• A veces la librer´ıa puede ser que haya sido desarrollada por un tercero:
libpetsc.a, libmkl.a.
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 15
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
El preprocesador CPP
• Muchas veces hay texto que se repite muchas veces en el c´odigo. En ese
caso se pueden usar macros
1 int v[100000];
2 if (n<100000) {
3 . . . .
4 }
Se puede simplificar de la siguiente forma
1 #define MAX 100000
2 int v[MAX];
3 if (n<MAX) {
4 . . . .
5 }
Estos macros son manejados por el preprocesador, el cual se llama
normalmente cpp (por C preprocesor). Podemos pensar que el CPP
genera un paso intermedio en el cual toma el archivo prog.cpp y genera
un archivo intermedio tempo.cpp que es el que finalmente es compilado.
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 16
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
El preprocesador CPP (cont.)
• CPP s´olo realiza manipulaciones a nivel de texto, no conoce nada
espec´ıfico del lenguaje C/C++, incluso puede usarse (y se usa) para otros
lenguajes como Fortran.
• Las directivas m´as usuales son
1 // Incluye todo el texto del archivo library.h
2 #include <library.h>
3
4 #define CHECK(a,n) if (a>n) error()
• Para #include el preprocesador simplemente incluye todo el archivo
mencionado en el punto donde se invoca el include.
• #define define un macro, despu´es se puede llamar al macro en otros
lugares del c´odigo y es reemplazado por su expansi´on. Los macros
pueden tener argumentos. Por convenci´on se suele dar a los macros
nombres en may´usculas.
• Se puede conocer cual es el resultado del CPP llamando a g++ con la
opci´on -E
1 $$ g++ -o tempo.cpp -E prog.cpp
• El CPP es un programa separado que se puede llamar por s´ı mismo
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 17
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
(/usr/bin/cpp).
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 18
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Chequeo de tipos
• C++ es un lenguaje tipado (aka tipeo est´atico, en ingl´es typed language),
es decir las variables tienen tipos definidos. El compilador chequea que
los resultados de las expresiones que se asignan a las variables
correspondan al tipo con el cual fueron definidas, caso contrario se
produce un error en tiempo de compilaci´on. Esto es bueno porque
permite detectar tempranamente errores. (Es equivalente al chequeo de
unidades en F´ısica).
1 // error: asigna un string a una variable entera
2 int a;
3 a = "Hello";
• Otros lenguajes (sobre todos los interpretados) hacen chequeo din´amico
de tipo, esto implica una p´erdida de eficiencia.
• El chequeo se hace tambi´en para los argumentos de una funci´on
1 void fun(int a,string s);
2 . . .
3 fun(23,45); // ERROR (45 no es un string!)
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 19
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Compilaci´on por separado
• En C++ se favorece que un programa grande se pueda dividir en
fracciones m´as peque˜nas. El mecanismo fundamental para dividir un
programa en partes m´as peque˜nas es usar funciones que realizan tareas
bien definidas. Por ejemplo podemos pensar en una funci´on int
gcd(int,int); que toma dos enteros y retorna el m´aximo com´un divisor
de los mismos.
• Las funciones tienen argumentos, una vez que la funci´on termina su
tarea, retorna un valor. Tambi´en puede ser que las funciones tengan
efectos colaterales (side effects) es decir que modifiquen sus
argumentos u otros objetos.
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 20
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Compilaci´on por separado (cont.)
• Para crear un programa que est´e dividido en varios archivos, el c´odigo de
un archivo debe poder usar las funciones del otro. Supongamos que un
archivo prog1.cpp contiene a la funci´on gcd(). Si queremos usar a gcd()
en el c´odigo de otro archivo prog2.cpp entonces el compilador debe estar
seguro que el tipo de los argumentos que se le van a pasar son los
correctos. Para eso hay que declarar a la funci´on en prog2.cpp antes de
poder llamarla
1 int gcd(int,int); // declara gcd()
2 . . .
3 r = gcd(m,n); // la puede usar porque ya
4 // fue declarada
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 21
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Declaraciones y definiciones
• Una declaraci´on le dice al compilador que esa funci´on existe y su
prototipo o signatura, es decir el tipo de argumentos de entrada y de
salida. Por ejemplo
1 int gcd(int,int);
• La definici´on por otra parte dice espec´ıficamente como la funci´on realiza
su tarea
1 int gcd(int x, int y) {
2 int a = x, b = y;
3 if (b>a) {
4 a = y; b = x;
5 }
6 while (true) {
7 int c = a % b;
8 if (c==0) return b;
9 a = b; b = c;
10 }
11 }
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 22
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Declaraciones y definiciones (cont.)
• Cada funci´on puede estar declarada varias veces en un archivo (mientras
la signatura de la funci´on sea la misma en cada una de las declaraciones).
1 int f(int x);
2 . . .
3 int f(int); // OK, misma signatura
• Por el contrario, la funci´on s´olo puede estar definida una sola vez en todos
los archivos del programa, ya que si no el compilador no sabr´ıa cual usar.
1 // archivo prog1.cpp
2 int f(int x) { return 2*x; }
3
4 // archivo prog2.cpp
5 int f(int x) { return 3*x; }
6 // -> ERROR: m´ultiplemente definida
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 23
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Definiciones y declaraciones de variables
Si declaramos una variable, por ejemplo
1 int m;
si bien parace una declaraci´on, en realidad ya tiene toda la informaci´on para
construir al objeto (un entero de 4 bytes) por lo tanto el compilador lo toma
adem´as como una definici´on. Por eso no podemos incluir dos veces esta
declaraci´on/definici´on, aunque sea del mismo tipo.
1 int m;
2 . . .
3 int m; // ERROR
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 24
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Definiciones y declaraciones de variables (cont.)
• Si queremos forzar a que sea una declaraci´on y no una definici´on
entonces debemos usar el keyword extern
1 extern int m;
2 . . .
3 extern int m; // OK
4 . . .
5 int m; // OK
• extern se puede usar tambi´en con las funciones, para hacer hincapi´e en
que es una declaraci´on, por ejemplo
1 extern int f(int x);
pero no es necesario.
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 25
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Incluyendo headers
• Es usual que en nuestros programas escribamos una serie de funciones
que despu´es utilizaremos en otras partes del programa.
1 // utils.cpp
2 int gcd(int m,int n) { /* . . . */ }
3 double cos(double alpha) { /* . . . */ }
4 double sin(double alpha) { /* . . . */ }
5 . . .
• Cuando queremos usar estas funciones en otro archivo fuente prog.cpp
primero tenemos que declararlas
1 // prog.cpp
2 int gcd(int m,int n);
3 double cos(double alpha);
4 double sin(double alpha);
5 . . .
6 int x = gcd(m,n);
7 double c = cos(alpha);
8 double s = sin(theta);
9 . . .
Esto se vuelve muy engorroso si hay que incluir las declaraciones en cada
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 26
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
uno de los archivos prog1.cpp, prog2.cpp... y utils.cpp tiene cientos de
funciones. Entonces para resolver esto incluimos todas las declaraciones
en un archivo header (cabecera) utils.h:
1 // utils.h
2 int gcd(int m,int n);
3 double cos(double alpha);
4 double sin(double alpha);
Entonces despu´es en prog1.cpp hay que solo incluir el header:
1 // prog1.cpp
2 #include "utils.h"
3 . . .
4 int x = gcd(m,n);
5 double c = cos(alpha);
6 double s = sin(theta);
7 . . .
Recordemos que lo que ocurre es que el preprocesador CPP se encarga
de buscar el archivo header y crear un archivo temporario donde la linea
del include es reemplazada por los contenidos del archivo.
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 27
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Incluyendo headers (cont.)
Hay dos versiones de include,
• Una que especifica archivos en forma relativa o absoluta
1 #include ". ./utils.h"
2 #include "utils2.h"
3 #include "/usr/include/utils3.h"
4 . . .
• Otra que busca los headers en una serie de directorios que el usuario
define en el comando de compilaci´on
1 $$ g++ -I/home/mstorti/utils -c -o prog.o prog.cpp
1 // lo encuentra en /home/mstorti/utils
2 #include <utils4.h>
3 // lo encuentra en /home/mstorti/utils/src
4 #include <src/utils5.h>
5 . . .
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 28
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Usando librer´ıas
• Entonces si tengo que usar una librer´ıa matrix que est´a compuesta de
varios archivos fuente matrix2.cpp, matrix1.cpp, matrix3.cpp... en realidad
no hace falta que compile todos estos archivos, mientras que el
desarrollador de esa librer´ıa provea
Un archivo libmatrix.a con todos los matrix<n>.cpp compilados.
Un archivo header con las declaraciones de las funciones matrix.h.
• Entonces para usar la librer´ıa basta con incluir el header
1 // myprog.cpp
2 #include <matrix.h>
3 . . .
y al linkeditar incluir la librer´ıa
1 $$ g++ myprog.cpp /usr/lib/libmatrix.a -o myprog
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 29
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Formato de include para C++
• La extensi´on que se usa para los archivos fuente puede ser .cpp, .cxx.
Para los headers se utiliza .h, .hpp, .hxx.
• Para evitar confusiones y ambig¨uedad con las extensiones, C++ introdujo
el concepto de include sin extensi´on. El traductor se encarga de convertir
el nombre y buscar la extensi´on.
1 #include <matrix>
• Existe una librer´ıa con muchas funciones muy ´utiles que es est´andar de C
y se llama justamente libc.a. Entre otras incluye funciones
Matem´aticas math.h: round, cos, sin, floor, ceil, ...
Input/output stdio.h: printf, scanf, read, write,
stdlib.h: rand, system, ...
En C++ estos headers es mejor incluirlos sin el .h y con una c:
1 #include <stdio.h> // C
2 #include <cstdio> // C++
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 30
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Un primer programa en C++
• Para imprimir por terminal hay que usar el operador << de la clase
iostream:
1 #include <iostream>
2 . . .
3 cout << "Hola";
El operador << en C quiere decir en realidad otra cosa: es para desplazar
los bits en un n´umero entero. Pero C++ permite redefinir los operadores
(lo que se llama sobrecarga de operadores) de manera que en este
contexto << quiere decir “enviar a”.
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 31
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Namespaces
• A medida que una librer´ıa o programa crecen cada vez hay m´as funciones
y es muy posible que se produzca la colisi´on de nombres. Por ejemplo, si
escribo una librer´ıa para manipular matrices, puedo querer implementar
una funci´on rand() que llena la matriz con n´umeros aleatorios.
Lamentablemente la libc ya usa el nombre rand() para generar un ´unico
numero aleatorio.
• Una soluci´on que se usaba en C era prependizar un prefijo identificador
de la librer´ıa a todas las funciones de la misma matrix_rand(),
matrix_sum(), matrix_prod(). Esto se vuelve muy engorroso.
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 32
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Namespaces (cont.)
• C++ provee un mecanismo para evitar colisiones llamado namespaces.
Todos los archivos de la librer´ıa se incluyen en un namespace de la
siguiente forma
1 // matrix.cpp
2 namespace matrix {
3 void rand(. . .) { /* . . . */ }
4 double sum(. . .) { /* . . . */ }
5 void prod(. . .) { /* . . . */ }
6 }
• Entonces despu´es las funciones se deben llamar con el operador de
scope ::: por ejemplo matrix::rand().
• Si en un archivo fuente se va a utilizar mucho una librer´ıa entonces puede
incluir todo el namespace, de manera que no hay que hacer el scope
1 // prog.cpp
2 using namespace matrix;
3
4 rand(A);
5 double m = max(A);
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 33
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Namespaces (cont.)
• Muchas utilidades y variables est´andar de C++, por ejemplo cout, est´an en
el namespace std de manera que o bien hay que hacer
1 std::cout << "Hola";
o si no
1 using namespace std;
2 . . .
3 cout << "Hola";
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 34
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Estructura de un programa
• Un programa en C/C++ est´a compuesto de una colecci´on de funciones y
variables. Cuando uno lanza el programa hay que determinar d´onde se
empieza a ejecutar el c´odigo, o sea el punto de entrada. En C/C++ el punto
de entrada es la funci´on main().
• La definici´on de una funci´on consiste en un valor de retorno, el nombre
de la funci´on y su lista de argumentos. El cuerpo de la funci´on (las
instrucciones que la componen) van entre llaves.
1 int function() {
2 // Function code here (this is a comment)
3 }
• Puede haber m´as pares de llaves balanceadas ({}) adentro de la funci´on
pero debe haber uno m´as externo que define el cuerpo de la funci´on.
• Como main() es una funci´on, debe respetar estos requisitos. main() no
tiene argumentos y retorna un int.
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 35
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Estructura de un programa (cont.)
• C/C++ es un lenguaje de formato libre (free form), la indentaci´on o la
posici´on de las variables en la l´ınea son irrelevantes.
• Tampoco es relevante la cantidad espacio en blanco (espacios, tabs, fin
de l´ınea). Cualquier cantidad de estos caracteres juntos es equivalente a
un solo espacio. De hecho un programa en C++ podr´ıa escribirse ne una
sola l´ınea.
• En C los comentarios van encerrados entre /* y */ (comentario multil´ınea).
En C++ se agreg´o un nuevo tipo de comentario que es por l´ınea desde un
// hasta el final de la l´ınea. (Esto viola un poco el concepto de free form).
1 /* Comentario multilinea tipo C */
2 int /* comentario en el medio del c´odigo */ x;
3 // Comentario por linea tipo C++
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 36
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Hello world
1 // Saying Hello with C++
2 #include <iostream> // Stream declarations
3 using namespace std;
4
5 int main() {
6 cout << "Hello, World. I am "
7 << 8 << " Today" << endl;
8 }
• Le pasamos a cout una serie de elementos de diferentes tipos: enteros,
arreglos de caracteres.
• endl es un final de l´ınea.
• En C se llama string a un pedazo de texto entre comillas. No confundir
con la clase string de C++ que cumple funciones similares pero es mucho
m´as potente. A los strings de C se los debe llamar m´as correctamente
arreglos de caracteres.
• Dentro del texto entre comillas se pueden incluir secuencias de escape
que permiten incluir caracteres especiales con precedidos de una barra
invertida: n es un caracter de fin de l´ınea, t un TAB, 0 un NULL,  una
barra invertida.
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 37
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Concatenaci´on de arreglos de caracters
• Para incluir arreglos de caracteres muy largos se puede simplemente
poner uno a continuaci´on de otro (puede ser en diferentes l´ıneas). El CPP
se encarga de juntarlos todos en una sola l´ınea: "aaa" "bbbb" es
completamente equivalente a "aaabbbb".
1 // Character array Concatenation
2 #include <iostream>
3 using namespace std;
4
5 int main() {
6 cout << "This is far too long to put on a "
7 "single line but it can be broken up with "
8 "no ill effectsnas long as there is no "
9 "punctuation separating adjacent character "
10 "arrays.n";
11 }
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 38
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Entrada de datos
cout es console output, cin es console input y permite ingresar datos.
1 // Converts decimal to octal and hex
2 #include <iostream>
3 using namespace std;
4
5 int main() {
6 int number;
7 cout << "Enter a decimal number: ";
8 cin >> number;
9 cout << "value in octal = 0"
10 << oct << number << endl;
11 cout << "value in hex = 0x"
12 << hex << number << endl;
13 }
oct y hex son manipulators, cambian el estado de cout.
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 39
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Llamando a otros programas
Dentro de la librer´ıa est´andar de C hay una funci´on muy potente system() que
permite llamar a otros programas desde un programa en C/C++. Se le pasa un
arreglo de caracteres con el comando que uno ejecutar´ıa en la l´ınea de
comandos.
1 // Call another program
2 #include <cstdlib> // Declare ‘‘system()’’
3 using namespace std;
4
5 int main() {
6 system("date -u");
7 }
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 40
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Strings de C
Manipular arreglos de caracteres en C se vuelve muy engorroso.
1 #include <iostream>
2 #include <cstring>
3 using namespace std;
4
5 int main() {
6 // concatenate two character arrays s1 and s2
7 char s1[ ] = "Hola ";
8 char s2[ ] = "mundo.";
9 cout << strlen(s1) << endl;
10 int n1 = strlen(s1);
11 int n2 = strlen(s2);
12 char *s = new char[n1+n2+1];
13 strncpy(s,s1,n1);
14 strncpy(s+n1,s2,n2);
15 s[n1+n2] = ’0’;
16 cout << s << endl;
17 delete[ ] s;
18 return 0;
19 }
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 41
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Strings de C++
Para eso C++ tiene objetos llamados strings que permiten manipularlos en
forma mucho m´as simple y con menor probabilidad de error.
1 #include <iostream>
2 #include <string>
3 using namespace std;
4
5 int main() {
6 // concatenate two character arrays s1 and s2
7 string s1 = "Hola ";
8 string s2 = "mundo.";
9 string s = s1 + s2;
10 cout << s << endl;
11 return 0;
12 }
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 42
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Strings de C++ (cont.)
1 //: C02:HelloStrings.cpp
2 // The basics of the Standard C++ string class
3 #include <string>
4 #include <iostream>
5 using namespace std;
6
7 int main() {
8 string s1, s2; // Empty strings
9 string s3 = "Hello, World."; // Initialized
10 string s4("I am"); // Also initialized
11 s2 = "Today"; // Assigning to a string
12 s1 = s3 + " " + s4; // Combining strings
13 s1 += " 8 "; // Appending to a string
14 cout << s1 + s2 + "." << endl;
15 }
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 43
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Escribir y leer de archivos
• Las funciones est´an declaradas en el header <fstream>.
• Para escritura hay que crear un objeto de tipo ofstream (como cout).
• Para lectura hay que crear un objeto de tipo ifstream (como cin).
• La funci´on getline(stream,s) lee una l´ınea de stream y la guarda en el
string s
1 // Copy one file to another, a line at a time
2 #include <string>
3 #include <fstream>
4 using namespace std;
5 int main() {
6 ifstream in("Scopy.cpp"); // Open for reading
7 ofstream out("Scopy2.cpp"); // Open for writing
8 string s;
9 while(getline(in, s)) // Discards newline char
10 out << s << "n"; // . . . must add it back
11 }
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 44
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Escribir y leer de archivos (cont.)
Otro ejemplo es guardar todo el archivo en un s´olo string:
1 // Read an entire file into a single string
2 #include <string>
3 #include <iostream>
4 #include <fstream>
5 using namespace std;
6
7 int main() {
8 ifstream in("FillString.cpp");
9 string s, line;
10 while(getline(in, line))
11 s += line + "n";
12 cout << s;
13 }
¿Que pasa si queremos guardar cada l´ınea en un string separado?
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 45
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
La clase vector
• Un vector es un contenedor que permite guardar un n´umero indefinido de
elementos en forma contigua e indexada.
• Se puede agrandar o achicar en forma din´amica, sin perder los elementos
preexistentes.
• Est´a templatizado o sea que se pueden definir vectores de diferentes
tipos: vector<int>, vector<double>, vector<string>,...
• La funci´on push_back() permite agregar un nuevo objeto al final del vector.
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 46
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
La clase vector (cont.)
1 // Copy an entire file into a vector of string
2 #include <string>
3 #include <iostream>
4 #include <fstream>
5 #include <vector>
6 using namespace std;
7
8 int main() {
9 vector<string> v;
10 ifstream in("Fillvector.cpp");
11 string line;
12 while(getline(in, line))
13 v.push-back(line); // Add the line to the end
14 // Add line numbers:
15 for(int i = 0; i < v.size(); i++)
16 cout << i << ": " << v[i] << endl;
17 }
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 47
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
La clase vector (cont.)
vector tambi´en puede guardar cualquier otro tipo, por ejemplo enteros:
1 // Creating a vector that holds integers
2 #include <iostream>
3 #include <vector>
4 using namespace std;
5
6 int main() {
7 vector<int> v;
8 for(int i = 0; i < 10; i++)
9 v.push-back(i);
10 for(int i = 0; i < v.size(); i++)
11 cout << v[i] << ", ";
12 cout << endl;
13 for(int i = 0; i < v.size(); i++)
14 v[i] = v[i] * 10; // Assignment
15 for(int i = 0; i < v.size(); i++)
16 cout << v[i] << ", ";
17 cout << endl;
18 }
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 48
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Ejercicios
1. Crear un programa que abre un archivo y cuenta las palabras (separadas
por whitespace). Ayuda: el operador >> lee de a palabras de un ifstream.
2. Crear un programa que cuenta la cantidad de caracteres que tiene un
archivo.
3. Crear un programa que cuenta la cantidad de ocurrencias de una palabra
espec´ıfica en un archivo. Ayuda: usar == para comparar strings.
4. Escribir un programa que imprime las l´ıneas de un archivo de texto en
orden inverso.
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 49
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
El C en C++
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 50
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Funciones
• Para evitar errores, C/C++ usa el concepto de prototipo o signatura de
funciones.
• Antes de usar una funci´on hay que declararla.
• Al usar la funci´on los argumentos con que es llamada deben coincidir con
el el tipo que fueron declarados.
1 int translate(float x, float y, float z);
2 int translate(float, float, float);
• En alg´un lugar la funci´on tiene que estar definida, aqu´ı los nombres de los
argumentos tienen que aparecer para poder ser usados en la funci´on
1 int translate(float x, float y, float z) {
2 x = y = z;
3 // . . .
4 }
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 51
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Valores de retorno
• La declaraci´on de la funci´on debe indicar el valor de retorno. Si la funci´on
no retorna nada usar void:
1 int f1(void); // Returns an int, takes no arguments
2 int f2(); // Like f1() in C++ but not in Standard C
3 float f3(float, int, char, double); // Returns a float
4 void f4(void); // Takes no arguments, returns nothing
• Para retornar el valor usar la sentencia return.
• Si la funci´on retorna void entonces no se debe llamar a return.
• Se puede tener m´as de un return en la funci´on. Son puntos de salida.
• El valor de retorno debe ser compatible con el indicado en la declaraci´on.
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 52
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Valores de retorno (cont.)
1 // Use of ‘‘return’’
2 #include <iostream>
3 using namespace std;
4
5 char cfunc(int i) {
6 if(i == 0)
7 return ’a’;
8 if(i == 1)
9 return ’g’;
10 if(i == 5)
11 return ’z’;
12 return ’c’;
13 }
14
15 int main() {
16 cout << "type an integer: ";
17 int val;
18 cin >> val;
19 cout << cfunc(val) << endl;
20 } ///:˜
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 53
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Usando la librer´ıa est´andar de C
• C incluye una librer´ıa de funciones est´andar (tambi´en llamada libc). Todos
los compiladores que satisfacen la norma deben incluir estas funciones
en su libc. Esto permite la portabilidad de los programas entre diferentes
compiladores.
• Muchos compiladores incluyen funciones adicionales que NO est´an en la
norma. Por lo tanto hay que prever que si se lleva el proyecto a otra
plataforma puede ser que estas funciones no existan en esa plataforma.
• La documentaci´on de las librer´ıas usualmente incluye la declaraci´on de la
funci´on y en que header (archivo .h) est´a.
• En caso que la librer´ıa no est´e documentada hay que directamente ver los
headers para encontrarel prototipo de la funci´on.
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 54
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Control de ejecuci´on. True and False
• Todas los condicionales (por ejemplo if o while) usan expresiones l´ogicas
como por ejemplo el resultado del operador de comparaci´on A==B. Esta
expresi´on retorna directamente un valor l´ogico true o false. No confundiir
con el operador de asignaci´on A=B.
• Lo mismo ocurre con otros operadores de comparaci´on
1 A==B; //It’s equal?
2 A!=B; //It’s distinct?
3 A<B; //It’s smaller?
4 A<=B; //It’s smaller or equal?
5 A>B; //It’s greater?
6 A>=B; //It’s greater or equal?
Si la expresi´on no retorna un valor booleano, entonces C trata de convertirlo.
Para todos los valores num´ericos (enteros, float, double, char, punteros) el
valor es falso si es cero, y en cualquier otra caso es verdadero. Entonces por
ejemplo el valor l´ogico de las siguientes expresiones es equivalente
1 if (n) { . . . }
2 if (n!=0) { . . . . }
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 55
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
3 if (!(n==0)) { . . . . } // ! is negation
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 56
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
If-else
El if puede existir de dos formas, con o sin else
1 if (expression)
2 statement
3
4 // o
5
6 if (expression)
7 statement
8 else
9 statement
En ambos casos statement puede ser una sentencia simple, terminada en una
coma, o compuesta, es decir un bloque de instrucciones encerrado en {}.
1 if (n>0) x=23; // sentencia simple
2
3 if (n>0) { // sentencia compuesta
4 x=23;
5 s="haha";
6 }
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 57
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
If-else (cont.)
1 int i;
2 cout << "type a number and ’Enter’" << endl;
3 cin >> i;
4 if(i > 5)
5 cout << "It’s greater than 5" << endl;
6 else
7 if(i < 5)
8 cout << "It’s less than 5 " << endl;
9 else
10 cout << "It’s equal to 5 " << endl;
11
12 cout << "type a number and ’Enter’" << endl;
13 cin >> i;
14 if(i < 10)
15 if(i > 5) // ‘‘if’’ is just another statement
16 cout << "5 < i < 10" << endl;
17 else
18 cout << "i <= 5" << endl;
19 else // Matches ‘‘if(i < 10)’’
20 cout << "i >= 10" << endl;
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 58
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
If-else (cont.)
Notar que todo el if act´ua como una sola instrucci´on, por eso no hace falta
encerrarlo con un {}.
1 if(i > 5)
2 cout << "It’s greater than 5" << endl;
3 else
4 if(i < 5)
5 cout << "It’s less than 5 " << endl;
6 else
7 cout << "It’s equal to 5 " << endl;
8
9 // es equivalente a
10
11 if(i > 5) { cout << "It’s greater than 5" << endl; }
12 else {
13 if(i < 5)
14 cout << "It’s less than 5 " << endl;
15 else
16 cout << "It’s equal to 5 " << endl;
17 }
Es una convenci´on mut ´util indentar ambos bloques del if para mejorar la
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 59
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
legibilidad.
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 60
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
while
while, do-while y for controlan lazos (loops) de ejecuci´on.
1 while(expression)
2 statement
Como antes statement puede ser simple o compuesto. La expresi´on se eval´ua
hasta que la condici´on de falso. Para que el lazo termine en alg´un momento
es necesario que statement tenga alg´un efecto que haga que eventualmente
expression de falso
1 int x=0;
2 while (x<5) x=34; // ejecuta una vez el lazo
3 x=0;
4 while (x<5) x=2; // ejecuta indefinidamente
5
6 x=0;
7 while (x<5) x++; // ejecuta el bloque 5 veces
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 61
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
while (cont.)
1 // Guess a number (demonstrates ‘‘while’’)
2 #include <iostream>
3 using namespace std;
4
5 int main() {
6 int secret = 15;
7 int guess = 0;
8 // != is the not-equal conditional:
9 while(guess != secret) { // Compound statement
10 cout << "guess the number: ";
11 cin >> guess;
12 }
13 cout << "You guessed it!" << endl;
14 }
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 62
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
while (cont.)
En C la condici´on dentro del condicional puede ser tan elaborada como se
quiera, la ´unica restricci´on es que debe retornar un valor l´ogico (o convertible
a l´ogico), incluso puede ser que el cuerpo del lazo este vac´ıo
1 while(do-a-lot-of-work()) ;
2 while(do-a-lot-of-work()) { }
por ejemplo
1 while(is-prime(n)) n++; // busca el primer n no primo
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 63
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
do-while
1 do
2 statement
3 while(expression);
Es similar al while pero ahora statement es ejecutado antes de verificar la
condici´on.
1 n=0;
2 while (n>0) /* body. . .*/ ; // body is not executed
3
4 n=0;
5 do
6 /* body. . .*/ ; // body is executed once
7 while (n>0);
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 64
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Lazo for
La forma del for es
1 for(initialization; conditional; step)
2 statement
Se utiliza mucho cuando simplemente se quiere ejecutar un bloque una serie
de veces bien definida
1 for (int i=0; i<n; i++) {
2 // This block is executed n times
3 }
Esto es completamente equivalente a
1 int i=0;
2 while(i<n) {
3 // This block is executed n times
4 i++;
5 }
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 65
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Break and continue
Adentro de cualquiera de los bloques while, do-while o for se puede usar
break para salir del lazo inmediatamente.
1 while (true) { // Infinite loop
2 cout << "Enter a number: ";
3 cin >> n;
4 if (is-prime(n)) break;
5 cout << n << " es un n´umero compuesto" << endl;
6 }
Si hay m´as de un lazo anidado entonces break sale del lazo m´as interno
1 for (int i=0; i<n; i++) {
2 for (int j=0; j<n; j++) {
3 if (j>i*i) break;
4 //. . .
5 }
6 // break transfers execution here
7 }
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 66
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Break and continue (cont.)
continue es similar a break pero hace que se ejecute la siguiente iteraci´on del
lazo
1 for (int j=0; j<n; j++) {
2 //. . . .
3 if (!is-prime(j)) continue;
4 // do this only for primes. . .
5 }
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 67
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
La sentencia switch
Va comparando la variable selector hasta que coincide con uno de los case
1 switch(selector) {
2 case integral-value1 : statement; break;
3 case integral-value2 : statement; break;
4 case integral-value3 : statement; break;
5 case integral-value4 : statement; break;
6 case integral-value5 : statement; break;
7 (. . .)
8 default: statement;
9 }
por ejemplo
1 char c;
2 //. . .
3 switch (c) {
4 case ’a’: cout << "It’s an a" << endl; break;
5 case ’b’: cout << "It’s a b" << endl; break;
6 default: cout << "Neither a or b" << endl;
7 }
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 68
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Si no se incluyen los break entonces la ejecuci´on sigue al siguiente case.
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 69
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
goto
La sentencia goto permite saltar a otro punto del programa. Se lo considera
muchas veces como una mala pr´actica de programaci´on, aunque a veces
puede ser ´util, por ejemplo para saltar de varios lazos anidados cuando se
encuentra una condici´on.
1 // The infamous goto is supported in C++
2 #include <iostream>
3 using namespace std;
4
5 int main() {
6 long val = 0;
7 for(int i = 1; i < 1000; i++) {
8 for(int j = 1; j < 100; j += 10) {
9 val = i * j;
10 if(val > 47000)
11 goto bottom;
12 // Break would only go to the outer ’for’
13 }
14 }
15 bottom: // A label
16 cout << val << endl;
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 70
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
17 }
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 71
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Recursion
Muchos problemas son intr´ınsecamente recursivos, es decir la soluci´on de un
problema est´a dada por la soluci´on de uno menor con el mismo algoritmo,
por ejemplo la definici´on de factorial se puede hacer en forma recursiva
n! = n · (n − 1)! (1)
en realidad esto es cierto si n > 1, la definici´on correcta es
n! =



1; si n = 1;
n · (n − 1)! ; si n > 1
(2)
decimos que el caso n = 1 corta la recursi´on.
Usando llamadas recursivas a funciones podemos implementar la funci´on
factorial
1 int factorial(int n) {
2 if (n==1) return 1;
3 else return n*factorial(n-1);
4 }
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 72
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Recursion (cont.)
La recursi´on es muy elegante para resolver problemas, pero puede ser
demandante en t´erminos de recursos. Es m´as simple si calculamos el
factorial con un lazo
1 int factorial(int n) {
2 int fac=1;
3 for (int j=2; j<=n; j++) fac *= j;
4 return fac;
5 }
El operador *= quiere decir aqu´ı
1 fac = fac*j;
Se puede aplicar a otros operadores binarios como +*-/, operadores l´ogicos
||&&, concatenaci´on de strings...
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 73
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Operadores
Los operadores no son m´as que funciones, con una sintaxis especial. Un
operador toma una o m´as series de valores y devuelve un resultado.
1 a = b + c;
podemos pensar que es traducido por el compilador en
1 a = sum(b,c);
Una cuesti´on importante con los operadores es la precedencia de los
mismos. Para los operadores matem´aticos es similar a las reglas que
aprendemos en la escuela
1 a = b * c + d;
es equivalente a
1 a = (b * c) + d;
porque * tiene mayor precedencia que +. Ante la duda, se pueden introducir
par´entesis para forzar el orden en que se eval´uan las expresiones.
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 74
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Operadores de auto incremento
El operador ++ es un atajo para una operaci´on muy com´un en programaci´on:
incrementar una variable de tipo entero en una unidad. Hay dos variantes,
prefija y postfija, ambos tienen el mismo efecto colateral (incrementar la
variable) pero en el prefijo retorna el valor de la variable incrementada, y el
postfijo sin incrementar
1 int m,n=5;
2 m = n++; // n=6, m=5
3
4 int m,n=5;
5 m = ++n; // n=6, m=6
Por ejemplo la siguiente funci´on retorna el primer primo siguiente (mayor o
igual) a n.
1 int next-prime(int n) {
2 while (!is-prime(n++)) { }
3 return n;
4 }
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 75
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Operadores de auto incremento (cont.)
Tambi´en hay autodecremento -- prefijo y postfijo.
1 int n=10;
2 while (n >= 0) cout << n-- << ", ";
3 cout << "Boom!!" << endl;
1 [mstorti@galileo garage]$$ ./boom.bin
2 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, Boom!!
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 76
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Tipos de datos
Dijimos que C/C++ es un lenguaje de tipeo est´atico, es decir en el momento
de crear las variables hay que decir de que tipo son. Hay tipos de datos
built-in como enteros, floats, strings, que ya est´an definidos en el compilador,
y tambi´en el programador puede crear sus propios tipos, muchas veces por
composici´on. Por ejemplo si estamos creando la base de datos de una
empresa podemos querer tener un tipo de dato employee que contenga un
string (el nombre), un entero (el n´umero de empleado) y un float (el sueldo).
Los tipos built-in son
• char un entero de al menos 8 bits, usualmente se usa para almacenar
caracteres.
• int un entero de al menos 16 bits (2 bytes)
• float un n´umero de punto flotante con al menos 4 bytes (simple precisi´on)
• double un n´umero de punto flotante con al menos 8 bytes (doble
precisi´on).
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 77
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Tipos de datos (cont.)
1 // Defining the four basic data
2 // types in C and C++
3
4 int main() {
5 // Definition without initialization:
6 char protein;
7 int carbohydrates;
8 float fiber;
9 double fat;
10 // Simultaneous definition & initialization:
11 char pizza = ’A’, pop = ’Z’;
12 int dongdings = 100, twinkles = 150,
13 heehos = 200;
14 float chocolate = 3.14159;
15 // Exponential notation:
16 double fudge-ripple = 6e-4;
17 }
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 78
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Tipos de datos (cont.)
Como los tipos b´asicos tienen una cantidad de bits fija pueden representar un
tama˜no m´aximo. Por ejemplo los enteros de 16 bits s´olo pueden estar entre
-32768 y +32768. Adem´as el tama˜no del tipo (la cantidad de bits) puede
depender de la m´aquina y del compilador, entonce los valores m´aximos y
m´ınimos (los l´ımites) est´an definidos en headers float.h y limits.h,
1 #include <climits>
2
3 cout << "Minimum and maximum integers are "
4 << endl << INT-MIN << " and " << INT-MAX
5 << endl;
6 }
1 [mstorti@galileo garage]$$ ./intmax.bin
2 Minimum and maximum integers are
3 -2147483648 and 2147483647
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 79
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Especificadores
• Para representar enteros se utiliza un bit de los 32 disponibles para
representar el signo.
• Si s´olo se van a utilizar enteros positivos entonces podemos usar ese bit
para extender un factor 2 el rango.
• int en el rango [-2147483648,2147483647]
• unsigned int en el rango [0,4294967295]
unsigned es un specifier, otros son: signed, unsigned, short, long.
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 80
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Especificadores (cont.)
1 //: C03:Specify.cpp
2 // Demonstrates the use of specifiers
3 #include <iostream>
4 using namespace std;
5
6 int main() {
7 char c;
8 unsigned char cu;
9 int i;
10 unsigned int iu;
11 short int is;
12 short iis; // Same as short int
13 unsigned short int isu;
14 unsigned short iisu;
15 long int il;
16 long iil; // Same as long int
17 unsigned long int ilu;
18 unsigned long iilu;
19 float f;
20 double d;
21 long double ld;
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 81
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
22 cout
23 << "n char= " << sizeof(c)
24 << "n unsigned char = " << sizeof(cu)
25 << "n int = " << sizeof(i)
26 << "n unsigned int = " << sizeof(iu)
27 << "n short = " << sizeof(is)
28 << "n unsigned short = " << sizeof(isu)
29 << "n long = " << sizeof(il)
30 << "n unsigned long = " << sizeof(ilu)
31 << "n float = " << sizeof(f)
32 << "n double = " << sizeof(d)
33 << "n long double = " << sizeof(ld)
34 << endl;
35 } ///:˜
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 82
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Especificadores (cont.)
1 [mstorti@galileo garage]$$ ./sizes.bin
2
3 char= 1
4 unsigned char = 1
5 int = 4
6 unsigned int = 4
7 short = 2
8 unsigned short = 2
9 long = 8
10 unsigned long = 8
11 float = 4
12 double = 8
13 long double = 16
14 [mstorti@galileo garage]$$
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 83
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Punteros
Al declarar variables lo que estamos haciendo es dar un nombre a un pedazo
de la memoria. Cuando decimos int n lo que estamos diciendo al compilador
es: res´erveme 4 bytes de la memoria y a partir de ahora lo voy a llamar n. El
operador & nos muestra en que posici´on de la memoria fue alocada la variable
1 int n;
2 cout << "variable n is in position " << &n << endl;
1 [mstorti@galileo garage]$$ ./ptr.bin
2 variable n is in position 0x7fff1c46d92c
Los punteros son impresos normalmente en formato de hexadecimales, si
quisi´eramos verlo en formato decimal podemos castear (convertir) el puntero
a un entero
1 int n;
2 cout << "variable n is in position " << (long)&n << endl;
1 [mstorti@galileo garage]$$ ./ptr.bin
2 variable n is in position 140737075615260
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 84
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Punteros (cont.)
1 #include <iostream>
2 using namespace std;
3
4 int dog, cat, bird, fish;
5
6 void f(int pet) {
7 cout << "pet id number: " << pet << endl;
8 }
9
10 int main() {
11 int i, j, k;
12 cout << "f(): " << (long)&f << endl;
13 cout << "dog: " << (long)&dog << endl;
14 cout << "cat: " << (long)&cat << endl;
15 cout << "bird: " << (long)&bird << endl;
16 cout << "fish: " << (long)&fish << endl;
17 cout << "i: " << (long)&i << endl;
18 cout << "j: " << (long)&j << endl;
19 cout << "k: " << (long)&k << endl;
20 }
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 85
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Punteros (cont.)
El resultado es
1 [mstorti@galileo garage]$$ ./pointers.bin
2 f(): 4196630
3 dog: 6295956
4 cat: 6295960
5 bird: 6295964
6 fish: 6295968
7 i: 140736631158572
8 j: 140736631158568
9 k: 140736631158564
10 [mstorti@galileo garage]$$
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 86
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Punteros (cont.)
• La direcci´on en memoria de un variable puede cambiar de una corrida a
otra.
• Funciones, variables y globales parecen estar en sectores de la memoria
diferentes.
• Enteros parecen ocupar 4 bytes.
• Las posiciones en la memoria se pueden guardar en una variable de tipo
especial llamada puntero
1 int number;
2 int *number-p = &number;
• El sufijo _p o simplemente p indica que es un puntero (es s´olo una
convenci´on).
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 87
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Punteros (cont.)
• Algunos programadores ponen el * junto al tipo.
1 int* number-p;
Es totalmente equivalente, pero confuso,
1 int* number-p,n-p,m-p;
Declara a number_p, pero n_p y m_p son declarados enteros. Lo correcto es
1 int *number-p,*n-p,*m-p;
• Podemos asignar a una variable de tipo puntero la direcci´on de una
variable, lo cual nos permite modificarla a trav´es de ese proxy
1 int number=100;
2 int *number-p = &number;
3 *number-p = 25; // Ahora number contiene 25!!
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 88
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Punteros (cont.)
• OJO: el hecho de declarar una variable de tipo puntero no significa que
est´e apuntando a un objeto v´alido, es deber del programador asignarle al
puntero una posici´on v´alida, si no puede dar error en tiempo de ejecuci´on
al querer usar el puntero.
1 int *p;
2 cout << "contenido de *p " << *p << endl; // ERROR
3 int x;
4 p = &x;
5 cout << "contenido de *p " << *p << endl; // OK
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 89
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Punteros (cont.)
Los punteros tienen un mont´on de usos, el primero que veremos es el de
causar que una funci´on modifique un objeto. El mecanismo de paso de
variables en C/C++ es por copia.
1 #include <iostream>
2 using namespace std;
3
4 void f(int a) {
5 cout << "&a = " << &a << endl;
6 cout << "a = " << a << endl;
7 a = 5;
8 cout << "a = " << a << endl;
9 }
10
11 int main() {
12 int x = 47;
13 cout << "&x = " << &x << endl;
14 cout << "x = " << x << endl;
15 f(x);
16 cout << "x = " << x << endl;
17 }
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 90
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Punteros (cont.)
Imprime:
1 [mstorti@galileo sources]$$ ./try40.bin
2 &x = 0x7ffe99dd33ec
3 x = 47
4 &a = 0x7ffe99dd33bc
5 a = 47
6 a = 5
7 x = 47
8 [mstorti@galileo sources]$$ x = 47
Como la variable a en f() es una copia, resulta que la modificaci´on que se
hace en f() no persiste, de manera que queda el mismo valor.
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 91
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Punteros (cont.)
En esta versi´on en cambio, pasamos la direcci´on donde est´a x:
1 #include <iostream>
2 using namespace std;
3
4 void f(int* p) {
5 cout << "p = " << p << endl;
6 cout << "*p = " << *p << endl;
7 *p = 5;
8 cout << "p = " << p << endl;
9 }
10
11 int main() {
12 int x = 47;
13 cout << "x = " << x << endl;
14 cout << "&x = " << &x << endl;
15 f(&x);
16 cout << "x = " << x << endl;
17 }
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 92
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Punteros (cont.)
Imprime:
1 [mstorti@galileo sources]$ ./try41.bin
2 x = 47
3 &x = 0x7ffcf3047dcc
4 p = 0x7ffcf3047dcc
5 *p = 47
6 p = 0x7ffcf3047dcc
7 x = 5
8 [mstorti@galileo sources]$
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 93
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Referencias
Los punteros son muy ´utiles pero engorrosos porque hay que estar
dereferenciando al puntero cada vez. C++ introdujo las referencias que son
completamente equivalentes a los punteros pero evitan la dereferenciaci´on.
1 #include <iostream>
2 using namespace std;
3
4 void f(int& r) {
5 cout << "r = " << r << endl;
6 cout << "&r = " << &r << endl;
7 r = 5;
8 cout << "r = " << r << endl;
9 }
10
11 int main() {
12 int x = 47;
13 cout << "x = " << x << endl;
14 cout << "&x = " << &x << endl;
15 f(x); // Looks like pass-by-value,
16 // is actually pass by reference
17 cout << "x = " << x << endl;
18 }
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 94
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Referencias (cont.)
Imprime:
1 [mstorti@galileo sources]$ ./try42.bin
2 x = 47
3 &x = 0x7ffd244d1aac
4 r = 47
5 &r = 0x7ffd244d1aac
6 r = 5
7 x = 5
8 [mstorti@galileo sources]$
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 95
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Punteros a void
• El compilador s´olo acepta que asignemos a una variable de tipo int* la
direcci´on de una variable de tipo int, en otro caso da un error
1 int *p;
2 int n;
3 p = &n; // OK
4 double a;
5 p = &a; // Error
• El tipo void* permite almacenar un puntero a cualquier tipo de variable
1 void* vp;
2 char c;
3 int i;
4 float f;
5 double d;
6 vp = &c;
7 vp = &i;
8 vp = &f;
9 vp = &d;
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 96
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Punteros a void (cont.)
• Una vez que una direcci´on es asignada a un void* el compilador no puede
saber de que tipo es el objeto al cual apunta, y por lo tanto no se puede
dereferenciar
1 int i = 99;
2 void* vp = &i;
3 *vp = 3; // Error de compilacion
• Para poder recuperar el objeto tenemos que castear el puntero, de esa
forma le estamos diciendo al compilador que es del tipo indicado
1 int i = 99;
2 void* vp = &i;
3 *((int*)vp) = 3; // OK!
• Si casteamos al tipo incorrecto el compilador no protesta, pero se puede
producir un error en tiempo de ejecuci´on
1 int i = 99;
2 void* vp = &i;
3 // Compila OK, posible error en tiempo de ejecuci´on
4 *((string*)vp) = "Hello world";
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 97
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Scope de las variables
Una variable existe desde su definici´on hasta la siguiente llave que cierra (}).
Eso se llama el scope de la variable.
1 // How variables are scoped
2 int main() {
3 int scp1;
4 // scp1 visible here
5 {
6 // scp1 still visible here
7 //. . . . .
8 int scp2;
9 // scp2 visible here
10 //. . . . .
11 {
12 // scp1 & scp2 still visible here
13 //. .
14 int scp3;
15 // scp1, scp2 & scp3 visible here
16 // . . .
17 } // scp3 destroyed here
18 // scp3 not available here
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 98
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
19 // scp1 & scp2 still visible here
20 // . . .
21 } // scp2 destroyed here
22 // scp3 & scp2 not available here
23 // scp1 still visible here
24 //. .
25 } // scp1 destroyed here
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 99
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Definiendo variables on-the-fly
En C todas las variables deben ser definidas al comienzo del scope. En C++
se pueden definir en cualquier lugar.
1 // On-the-fly variable definitions
2 #include <iostream>
3 using namespace std;
4
5 int main() {
6 //. .
7 { // Begin a new scope
8 int q = 0; // C requires definitions here
9 //. .
10 // Define at point of use:
11 for(int i = 0; i < 100; i++) {
12 q++; // q comes from a larger scope
13 // Definition at the end of the scope:
14 int p = 12;
15 }
16 int p = 1; // A different p
17 } // End scope containing q & outer p
18 cout << "Type characters:" << endl;
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 100
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
19 while(char c = cin.get() != ’q’) {
20 cout << c << " wasn’t it" << endl;
21 if(char x = c == ’a’ | | c == ’b’)
22 cout << "You typed a or b" << endl;
23 else
24 cout << "You typed " << x << endl;
25 }
26 cout << "Type A, B, or C" << endl;
27 switch(int i = cin.get()) {
28 case ’A’: cout << "Snap" << endl; break;
29 case ’B’: cout << "Crackle" << endl; break;
30 case ’C’: cout << "Pop" << endl; break;
31 default: cout << "Not A, B or C!" << endl;
32 }
33 }
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 101
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Definiendo variables on-the-fly (cont.)
Las variables que est´an fuera de todas las funciones son globales, su scope
es todo el programa, inclu´ıdo dentro de las funciones.
1 // == file1.cpp ==
2 // Demonstration of global variables
3 #include <iostream>
4 using namespace std;
5
6 int globe;
7 void func();
8 int main() {
9 globe = 12;
10 cout << globe << endl;
11 func(); // Modifies globe
12 cout << globe << endl;
13 }
14 // == file2.cpp ==
15 // Accessing external global variables
16 extern int globe;
17 // (The linker resolves the reference)
18 void func() {
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 102
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
19 globe = 47;
20 }
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 103
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Variables locales
Las variables que existen dentro de un scope son locales, tambi´en se les
llama autom´aticas ya que son creadas en el momento de llegar a ese bloque.
La memoria que le es asignada no tiene porque ser siempre la misma, por lo
tanto la variable no retiene el valor que le fue asignado antes.
1 void f(int x) {
2 int a;
3 cout << "a en f(): " << a << endl;
4 cout << "&a en f(): " << &a << endl;
5 a=x;
6 cout << "a en f() despues de asignar: " << a << endl;
7 }
8
9 void g(int x) {
10 int a;
11 cout << "a en g(): " << a << endl;
12 cout << "&a en g(): " << &a << endl;
13 a=x;
14 cout << "a en g() despues de asignar: " << a << endl;
15 }
16
17 void h(int x) {
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 104
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
18 int a;
19 f(435);
20 cout << "a en h(): " << a << endl;
21 cout << "&a en h(): " << &a << endl;
22 a=x;
23 cout << "a en h() despues de asignar: " << a << endl;
24 }
25
26 int main() {
27 f(23);
28 g(45);
29 f(23);
30 g(45);
31 h(234);
32 return 0;
33 }
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 105
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Variables locales (cont.)
El resultado es:
1 [mstorti@galileo garage]$$ ./try2.bin
2 a en f(): 0
3 &a en f(): 0x7fff6df56d1c
4 a en f() despues de asignar: 23
5 a en g(): 23
6 &a en g(): 0x7fff6df56d1c
7 a en g() despues de asignar: 45
8 a en f(): 45
9 &a en f(): 0x7fff6df56d1c
10 a en f() despues de asignar: 23
11 a en g(): 23
12 &a en g(): 0x7fff6df56d1c
13 a en g() despues de asignar: 45
14 a en f(): 59
15 &a en f(): 0x7fff6df56cdc
16 a en f() despues de asignar: 435
17 a en h(): 45
18 &a en h(): 0x7fff6df56d1c
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 106
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
19 a en h() despues de asignar: 234
20 [mstorti@galileo garage]$$
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 107
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Punteros a variables locales
Si una variable sale de scope, es un error tratar de utilizar punteros que
apuntaban a esa variable.
1 int *p;
2 for (int j=0; j<N; j++) {
3 int z;
4 p = &z;
5 . . .
6 }
7 // ERROR (z no existe mas)
8 cout << "contenido de *p " << *p << endl;
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 108
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Variables est´aticas
Si queremos que el ´area asignada a una variable local sea siempre el mismo,
entonces le agregamos el keyword static. Un ejemplo cl´asico es una funci´on
que cuenta cuantas veces fue llamada:
1 void f() {
2 static int count=0;
3 cout << "f() fue llamada " << count << " veces" << endl;
4 cout++;
5 }
6
7 int main() {
8 for (int j=0; j<10; j++)
9 f();
10 return 0;
11 }
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 109
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Variables est´aticas (cont.)
El resultado es:
1 [mstorti@galileo garage]$ ./try14.bin
2 f() fue llamada 0 veces
3 f() fue llamada 1 veces
4 f() fue llamada 2 veces
5 f() fue llamada 3 veces
6 f() fue llamada 4 veces
7 f() fue llamada 5 veces
8 f() fue llamada 6 veces
9 f() fue llamada 7 veces
10 f() fue llamada 8 veces
11 f() fue llamada 9 veces
12 [mstorti@galileo garage]$
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 110
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Constantes
Si se utilizar´a muchas veces un valor que es constante se pueden hacer a
trav´es de un macro
1 #define PI 3.141459
o bien a trav´es de una variable de tipo const
1 const double pi = 3.141459;
Es m´as prolijo esto ´ultimo (le permite al compilador hacer chequeo de tipo).
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 111
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Operadores. Asignaci´on
El caracter = se utiliza como el operador de asignaci´on:
1 A=4;
Lo que est´a a la izquierda de = es el lvalue y lo que est´a a la derecha el rvalue.
El rvalue puede ser cualquier expresi´on. El compilador la evalua y asigna el
resultado a lo que est´a en el lvalue. Ahora bien lo que est´a en el lvalue no
puede ser cualquier cosa, debe ser una variable o cualquier otra cosa a la
cual se le pueda asignar un valor. Por ejemplo no puede ser una constante, es
decir no podemos hacer
1 4=A;
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 112
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Operadores matem´aticos
Los operadores matem´aticos binarios usuales son +-*/. Cada uno de ellos se
puede usar en forma de acumulaci´on +=, -=, *=, /=. Por ejemplo
1 x += 5;
es equivalente a
1 x = x + 5;
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 113
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Operadores relacionales
Son
1 >, <, >=, <=, ==, !=
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 114
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Operadores l´ogicos
Son && (and) y || (or). Recordar que en C/C++ muchos tipos se castean
autom´aticamente a bool, siendo 0 el valor falso y cualquier otro valor
verdadero. Cuando se imprimen los valores booleanos dan 0 o 1. ! es la
negaci´on.
Son operadores cortocircuitados es decir si hacemos
1 expr1 && expr2
entonces primero se evalua expr1 y si da falso, entonces expr2 NO se eval´ua,
ya que no es necesario porque la expresi´on l´ogica resultar´a en falso de todas
formas. Eso puede ser importante, por ejemplo
1 if (n>0 && m/n!=3) . . .
est´a garantizado que no dar´a error si n==0 ya que si es as´ı directamente la
divisi´on por n no se har´a. Lo mismo ocurre en
1 expr1 | | expr2
si la primera da verdadero.
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 115
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
El operador hook
Es una forma muy compacta de escribir un if-else. Por ejemplo esta expresi´on
calcula el m´ınimo de dos valores
1 x = (m<n ? m : n);
Se puede usar tambi´en en un lvalue. La siguiente expresi´on asigna al menor
de m,n el valor 23.
1 (m<n ? m : n) = 23;
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 116
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Errores comunes con los operadores
• Las reglas de precedencia a veces son simples, pero si se escriben
expresiones complejas ya no. Ante la duda utilizar par´entesis.
• No confundir = con ==.
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 117
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Operadores de cast
• Si el compilador ve que estamos mezclando tipos en una asignaci´on,
insertar´a una operaci´on de cast (conversi´on de tipo) autom´aticamente
1 int x=5;
2 double z=x; // OK
3 z=23.3;
4 x=z; // se pierde la mantisa (truncamiento)
5 x = (int) z; // cast explicito
6 x = int(z); // otra forma del cast explicito
7
8 int ixp = &x; // error, no puede convertir ptr a int
9 long int ixp2 = (long int)&x; // OK!
10 long int ixp3 = static-cast<long int>(&x); // OK!
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 118
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Operador sizeof
• Retorna el tama˜no de una variable o tipo en bytes
1 cout << "sizeof(char) " << sizeof(char) << endl; // ->1
2 cout << "sizeof(int) " << sizeof(int) << endl; // ->4
3 cout << "sizeof(float) " << sizeof(float) << endl; // ->4
4 cout << "sizeof(double) " << sizeof(double) << endl; // ->8
5
6 double a;
7 cout << "sizeof(a) " << sizeof(a) << endl; // ->8
8 cout << "sizeof(&a) " << sizeof(&a) << endl; // ->8 (in x86-64)
9 int x;
10 cout << "sizeof(&x) " << sizeof(&x) << endl; // ->8 (in x86-64)
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 119
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
typedef: Aliases de tipos
• Permite hacer un alias de un tipo a un nuevo tipo
1 typedef unsigned long int ulong;
2 . . .
3 ulong x;
• Simple para tipos b´asicos, m´as complicado para punteros
1 typedef int *int-p;
• La regla es que se escribe una l´ınea como la declaraci´on de una variable
con typedef al principio y reemplazando la variable por el tipo.
• Esto permite hacer expresiones m´as cortas pero adem´as tiene un uso muy
importante. Permitir cambiar de tipo todas las variables de un programa
1 typedef float scalar;
2 scalar i,j,k;
Para cambiar todo el programa a doble precisi´on:
1 typedef double scalar;
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 120
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Estructuras
• Se pueden definir nuevos tipos agrupando varios miembros en una
estructura. Los miembros de la estructura se toman con el operador .:
1 struct A {
2 char c;
3 int m;
4 float f;
5 double b;
6 };
7
8 void printa(A a) {
9 cout << "structure is (" << a.c << "," << a.m << ","
10 << a.f << "," << a.b << ")" << endl;
11 }
12 . . .
13
14 A a1, a2;
15 a1.c = ’h’;
16 a2.m = 23;
17 printa(a1);
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 121
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Estructuras (cont.)
Se pueden tomar punteros a estructuras y enlazarlas
1 struct cell {
2 char c;
3 double x;
4 cell *next;
5 };
6
7 int main() {
8 cell c1,c2,c3;
9 c1.c = ’a’; c1.x = 1; c1.next = &c2;
10 c2.c = ’b’; c2.x = 2; c2.next = &c3;
11 c3.c = ’c’; c3.x = 3; c3.next = &c1;
12
13 cell *cp = &c1;
14 for (int k=0; k<20; k++) {
15 cout << "cp " << cp << ", c "
16 << (*cp).c << ", x " << (*cp).x << endl;
17 cp = (*cp).next;
18 }
19 }
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 122
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Estructuras (cont.)
1 cell c1,c2,c3;
2 c1.c = ’a’; c1.x = 1; c1.next = &c2;
3 c2.c = ’b’; c2.x = 2; c2.next = &c3;
4 c3.c = ’c’; c3.x = 3; c3.next = &c1;
c='a' x=1
next
c1
c='b' x=2
next
c2
c='c' x=3
next
c3
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 123
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Estructuras (cont.)
El resultado es
1 [mstorti@galileo garage]$$ ./try8.bin
2 cp 0x7fff571b2d20, c a, x 1
3 cp 0x7fff571b2d00, c b, x 2
4 cp 0x7fff571b2ce0, c c, x 3
5 cp 0x7fff571b2d20, c a, x 1
6 . . .
7 cp 0x7fff571b2d20, c a, x 1
8 cp 0x7fff571b2d00, c b, x 2
9 [mstorti@galileo garage]$$
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 124
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Arrow operator
Como en el ejemplo anterior es muy com´un la compinaci´on (*cp).x es decir
tener un puntero a una estructura cp y querer tomar un miembro x de la
estructura apuntada. Como es tan com´un hay un atajo sint´actico para eso
1 (*cp).x es equivalente a cp->x
Entonces el lazo del programa anterior pasa a ser
1 for (int k=0; k<20; k++) {
2 cout << "cp " << cp << ", c " << cp->c
3 << ", x " << cp->x << endl;
4 cp = cp->next;
5 }
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 125
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Enum’s
• Supongamos que queremos definir una estructura shape que contiene una
forma geom´etrica, digamos las coordenadas x,y de su centro y un entero
que indica su forma. Para ello incluimos un entero gtype (por geometric
type) que define que tipo de forma es. Podemos por ejemplo asignar
arbitrariamente gtype=0 para c´ırculos, 1=cuadrados, 2=rect´angulos.
1 struct shape {
2 double x,y;
3 int gtype;
4 };
Entonces una funci´on que imprime la forma ser´ıa algo as´ı como
1 void draw(shape s) {
2 if (s.gtype==0) //. . . imprime un circulo
3 else if (s.gtype==1) //. . . imprime un cuadrado
4 else if (s.gtype==2) //. . . imprime un rect
5 . . .
6 }
El problema con esto es que tenemos que guardar mentalmente una tabla
para saber que entero correspond´ıa a cada forma.
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 126
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Enum’s (cont.)
Una posibilidad es usar macros
1 #define CIRCLE 0
2 #define SQUARE 1
3 #define RECTANGLE 2
4
5 void draw(shape s) {
6 if (s.gtype==CIRCLE) //. . . imprime un circulo
7 else if (s.gtype==SQUARE) //. . . imprime un cuadrado
8 else if (s.gtype==RECTANGLE) //. . . imprime un rect
9 . . .
10 }
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 127
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Enum’s (cont.)
Pero, como ya dijimos, es preferible no usar macros, para esto est´a el enum:
1 enum GeoType { circle, square, rectangle};
2
3 struct shape {
4 double x,y;
5 GeoType gtype;
6 };
7
8 void draw(shape s) {
9 if (s.gtype==circle) //. . . imprime un circulo
10 else if (s.gtype==square) //. . . imprime un cuadrado
11 else if (s.gtype==rectangle) //. . . imprime un rect
12 . . .
13 }
• Internamente los enums son enteros, pero esto es transparente para
nosotros.
• El compilador traduce cada identificador de la lista a un entero
consecutivo.
• Se puede forzar a que tomen un valor espec´ıfico
1 enum GeoType { circle=5, square=10, rectangle=15};
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 128
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Arreglos de estructuras
• Vimos que podemos definir arreglos como int v[100].
• Tambi´en lo podemos hacer con estructuras cell cellv[100]
• Los elementos son guardados en forma consecutiva
1 struct cell {
2 double x;
3 cell *next;
4 };
5
6 for (int j=0; j<4; j++)
7 cout << "&cellv[" << j << "] "
8 << (long int)&cellv[j] << endl;
9 . . .
10 &cellv[0] 140736201505632
11 &cellv[1] 140736201505648
12 &cellv[2] 140736201505664
ya que el tama˜no de la celda es de 16 bytes (8 para el doble y 8 para el
puntero):
1 cout << "sizeof(cell): " << sizeof(cell) << endl;
2 . . .
3 sizeof(cell): 16
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 129
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Punteros y arreglos
Si imprimimos un arreglo, el compilador lo imprime como hexadecimal, o sea
como si fuera un puntero
1 int v[100];
2 cout << v << endl;
3 . . .
4 -> 0x7fff7e388420
Esto es porque el compilador s´olo almacena para el vector la direcci´on donde
comienza el ´area asignada al vector. Esto lo podemos verificar imprimiento la
direcci´on del primer elemento
1 cout << &cellv[0] << endl;
2 -> 0x7fff7e388420
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 130
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Punteros y arreglos (cont.)
Si tomamos un puntero al primer elemento podemos manipular al vector a
trav´es de ese puntero
1 int v[100];
2 int *p= &v[0];
3 for (int j=0; j<100, j++) *(p+j) = 100*j;
De hecho en la mayor´ıa de los casos punteros y arreglos son intercambiables,
por ejemplo a los punteros se les puede aplicar el operador [] de manera que
se lo puede utilizar como un vector.
1 int v[100];
2 int *p= &v[0];
3 for (int j=0; j<1000, j++) p[j] = 100*j;
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 131
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Arreglos de punteros
• Tambi´en se pueden tener arreglos de punteros
1 int *v[100]; // arreglo de 100 punteros a enteros
• Los arreglos de caracteres, son de tipo char* entonces si queremos tener
un arreglo de “strings de C”, tenemos un arreglo de arreglos de char, o lo
que es equivalente a arreglos de punteros a char
1 char *as[ ];
2 char **as; // equivalente
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 132
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Arreglos de punteros (cont.)
• Un caso frecuente de esto es la segunda forma de llamada a main(). Si
llamamos a nuestro programa con argumentos
1 int main(int argc,char **argv) {
2 for (int j=0; j<argc; j++)
3 cout << j << ": " << argv[j] << endl;
4 return 0;
5 }
El resultado es
1 $$ ./try10.bin -u mstorti -d 453 -l 34 -f 34.56
2 0: ./try10.bin
3 1: -u
4 2: mstorti
5 3: -d
6 4: 453
7 5: -l
8 6: 34
9 7: -f
10 8: 34.56
El shell (en este caso bash) divide los argumentos pasados en la l´ınea de
comando por whitespace y construye un arreglo de strings
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 133
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Arreglos de punteros (cont.)
• El acceso a elementos de un arreglo de C es extremadamente r´apido.
• Sin embargo si se accede a posiciones m´as all´a de la ´ultima posici´on del
vector se puede producir un error
1 int v[100];
2 . . .
3 v[100] = x; // Muy probablemente SIGSEGV o SEGFAULT
• Se debe conocer el tama˜no del vector en tiempo de compilaci´on (hay una
forma de hacerlo din´amico, con new[]/delete[] o malloc()/free().
• La clase vector<> es mucho m´as vers´atil y m´as segura.
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 134
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Arreglos de punteros (cont.)
Podemos verificar que los elementos de un vector est´an en posiciones
contiguas.
1 int a[10];
2 cout << "sizeof(int) = "<< sizeof(int) << endl;
3 for(int i = 0; i < 10; i++)
4 cout << "&a[" << i << "] = "
5 << (long)&a[i] << endl;
produce
1 $$ ./try17.bin
2 sizeof(int) = 4
3 &a[0] = 140736359816368
4 &a[1] = 140736359816372
5 &a[2] = 140736359816376
6 &a[3] = 140736359816380
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 135
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Aritm´etica de punteros
Se pueden hacer cuentas con punteros de tipo ptr = ptr + int y todas las
derivadas, por ejemplo
1 ptr = ptr + int
2 int = ptr - ptr
3 ptr += int
4 ptr++
5 ptr--
En todas estas operaciones el entero indica posiciones en el vector, no bytes.
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 136
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Aritm´etica de punteros (cont.)
1 int i[10];
2 double d[10];
3 int* ip = i;
4 double* dp = d;
5 cout << "ip = " << (long)ip << endl;
6 ip++;
7 cout << "ip = " << (long)ip << endl;
8 cout << "dp = " << (long)dp << endl;
9 dp++;
10 cout << "dp = " << (long)dp << endl;
produce
1 [mstorti@galileo garage]$$ ./try18.bin
2 ip = 140733418503296
3 ip = 140733418503300
4 dp = 140733418503216
5 dp = 140733418503224
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 137
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Tama˜nos de estructuras
Cuando se usan estructuras con tipos mezclados puede ser que el tama˜no del
tipo combinado no sea igual a la suma de los tama˜nos de los tipos (pero
seguro es mayor o igual) porque el compilador tiene que alinear los tipos.
1 struct A {
2 char c;
3 double d;
4 };
da sizeof(A) -> 16, y
1 struct B { char c; double d; char c2; };
2 struct C { char c; char c2; double d; };
da
1 sizeof(B) -> 24
2 sizeof(C) -> 16
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 138
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Programaci´on Orientada
a Objetos
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 139
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Abstracci´on de datos
Un contenedor de elementos de longitud arbitraria
1 #ifndef CSTASH-H
2 #define CSTASH-H
3
4 struct CStash {
5 int size; // Size of each space
6 int quantity; // Number of storage spaces
7 int next; // Next empty space
8 // Dynamically allocated array of bytes:
9 unsigned char* storage;
10 };
11
12 void initialize(CStash* s, int size);
13 void cleanup(CStash* s);
14 int add(CStash* s, const void* element);
15 void* fetch(CStash* s, int index);
16 int count(CStash* s);
17 void inflate(CStash* s, int increase);
18
19 #endif
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 140
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Abstracci´on de datos (cont.)
1 struct CStash {
2 int size; // Size of each space
3 int quantity; // Number of storage spaces
4 int next; // Next empty space
5 // Dynamically allocated array of bytes:
6 unsigned char* storage;
7 };
store
quantity
next
size
used free
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 141
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Abstracci´on de datos (cont.)
1 // Implementation of example C-like library
2 // Declare structure and functions:
3 #include "./cstash.h"
4 #include <iostream>
5 #include <cassert>
6
7 using namespace std;
8 // Quantity of elements to add
9 // when increasing storage:
10 const int increment = 100;
11
12 void initialize(CStash* s, int sz) {
13 s->size = sz;
14 s->quantity = 0;
15 s->storage = 0;
16 s->next = 0;
17 }
18
19 int add(CStash* s, const void* element) {
20 if(s->next >= s->quantity) //Enough space left?
21 inflate(s, increment);
22 // Copy element into storage,
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 142
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
23 // starting at next empty space:
24 int startBytes = s->next * s->size;
25 unsigned char* e = (unsigned char*)element;
26 for(int i = 0; i < s->size; i++)
27 s->storage[startBytes + i] = e[i];
28 s->next++;
29 return(s->next - 1); // Index number
30 }
31
32 void* fetch(CStash* s, int index) {
33 // Check index boundaries:
34 assert(0 <= index);
35 if(index >= s->next)
36 return 0; // To indicate the end
37 // Produce pointer to desired element:
38 return &(s->storage[index * s->size]);
39 }
40
41 int count(CStash* s) {
42 return s->next; // Elements in CStash
43 }
44
45 void inflate(CStash* s, int increase) {
46 assert(increase > 0);
47 int newQuantity = s->quantity + increase;
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 143
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
48 int newBytes = newQuantity * s->size;
49 int oldBytes = s->quantity * s->size;
50 unsigned char* b = new unsigned char[newBytes];
51 for(int i = 0; i < oldBytes; i++)
52 b[i] = s->storage[i]; // Copy old to new
53 delete [ ](s->storage); // Old storage
54 s->storage = b; // Point to new memory
55 s->quantity = newQuantity;
56 }
57
58 void cleanup(CStash* s) {
59 if(s->storage != 0) {
60 cout << "freeing storage" << endl;
61 delete [ ]s->storage;
62 }
63 }
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 144
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Abstracci´on de datos (cont.)
• CStash es un tipo que permite almacenar una cantidad ilimitada de
elementos de tama˜no size.
• Tiene un ´area de almacenamiento interno unsigned char *storage.
• Se pueden agregar elementos con add(), si el tama˜no del almacenamiento
interno no es suficiente entences se incrementa en una dada cantidad
(por default 100).
• initialize() realiza la inicializacion de la estructura, poniendo a cero los
diferentes contadores y el tama˜no de los elementos al valor entrado por el
usuario (int sz).
• add() agrega un elemento copi´andolo byte por byte a storage. Si el tama˜no
no es suficiente llama a inflate() para alocar una nueva ´area recopiando
todo el ´area previa y agregando el nuevo elemento.
• quantity es el n´umero de lugares disponibles
next es la cantidad de lugares realmente ocupados.
• fetch() retorna el puntero al lugar donde comienza el elemento en la
posici´on index. Primero chequea que efectivamente el ´ındice est´e en el
rango de valores apropiados (0<=index<next). En caso contrario retorna un
puntero nulo. Est´a garantizado que el puntero nulo no apunta a ning´un
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 145
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
lado de la memoria.
• count() retorna la cantidad de elementos que hay en el contenedor.
Simplemente retorna next.
• Alocaci´on din´amica de memoria: Como no sabemos en principio que
tama˜no va a tomar el ´area de memoria vamos alocando din´amicamente
con el operador new
1 new unsigned char[newBytes];
• En general se puede hacer
1 t = new Type; // aloca un solo objeto
2 tp = new Type[count]; // aloca un arreglo de count objetos
• El ´area utilizada debe ser liberada. Si no (y si la alocaci´on se hace
repetidamente) se produce un memory leak.
1 delete t;
2 delete[ ] tp;
• Las ´areas de memoria reservadas con new se alocan en el heap. Si el heap
se acaba la alocaci´on da un error (OJO que no necesariamente retorna un
puntero nulo).
• Los pedazos de memoria alocados con new pueden crear fragmentaci´on
de la memoria. (No hay un defragmentador).
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 146
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Abstracci´on de datos (cont.)
1 #include "./cstash.h"
2 #include <fstream>
3 #include <iostream>
4 #include <string>
5 #include <cassert>
6 using namespace std;
7
8 int main() {
9 // Define variables at the beginning
10 // of the block, as in C:
11 CStash intStash, stringStash;
12 int i;
13 char* cp;
14 ifstream in;
15 string line;
16 const int bufsize = 80;
17 // Now remember to initialize the variables:
18 initialize(&intStash, sizeof(int));
19 for(i = 0; i < 100; i++)
20 add(&intStash, &i);
21 for(i = 0; i < count(&intStash); i++)
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 147
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
22 cout << "fetch(&intStash, " << i << ") = "
23 << *(int*)fetch(&intStash, i)
24 << endl;
25 // Holds 80-character strings:
26 initialize(&stringStash, sizeof(char)*bufsize);
27 in.open("./trycstash.cpp");
28 assert(in);
29 while(getline(in, line))
30 add(&stringStash, line.c-str());
31 i = 0;
32 while((cp = (char*)fetch(&stringStash,i++))!=0)
33 cout << "fetch(&stringStash, " << i << ") = "
34 << cp << endl;
35 cleanup(&intStash);
36 cleanup(&stringStash);
37 return 0;
38 }
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 148
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Abstracci´on de datos (cont.)
Resultado:
1 [mstorti@galileo garage]$ ./trycstash.bin
2 fetch(&intStash, 0) = 0
3 fetch(&intStash, 1) = 1
4 fetch(&intStash, 2) = 2
5 fetch(&intStash, 3) = 3
6 . . .
7 fetch(&intStash, 97) = 97
8 fetch(&intStash, 98) = 98
9 fetch(&intStash, 99) = 99
10 0: #include "./cstash.h"
11 1: #include <fstream>
12 2: #include <iostream>
13 3: #include <string>
14 . . .
15 37: cleanup(&stringStash);
16 38: return 0;
17 39: }
18 freeing storage
19 freeing storage
20 [mstorti@galileo garage]$
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 149
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
POO b´asica
La librer´ıa que creamos tiene dos problemas b´asicos:
• Ser´ıa bueno que la construcci´on y destrucci´on de los objetos fuera
autom´atica.
• Poluci´on del espacio de nombres: Si necesitamos otro contenedor no
vamos a poder usar los nombres initialize() y cleanup(). Una posible
soluci´on ser´ıa usar nombres con prefijos CStash_initialize(),
CStash_cleanup() ...
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 150
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
POO b´asica (cont.)
1 struct Stash {
2 int size; // Size of each space
3 int quantity; // Number of storage spaces
4 int next; // Next empty space
5 // Dynamically allocated array of bytes:
6 unsigned char* storage;
7 // Functions!
8 void initialize(int size);
9 void cleanup();
10 int add(const void* element);
11 void* fetch(int index);
12 int count();
13 void inflate(int increase);
14 };
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 151
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
POO b´asica (cont.)
• Ahora las funciones aparecen dentro de la estructura, de manera que esta
act´ua como un namespace, de manera que la funciones se llaman ahora
Stash::initialize(), Stash::cleanup()
• No hace falta pasar a las funciones el puntero al objeto. Esto se hace
autom´aticamente llamando a la funci´on como miembro de un objeto
1 Stash s1,s2,s3;
2 s1.initialize(10);
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 152
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
POO b´asica (cont.)
1 // C library converted to C++
2 // Declare structure and functions:
3 #include "CppLib.h"
4 #include <iostream>
5 #include <cassert>
6 using namespace std;
7 // Quantity of elements to add
8 // when increasing storage:
9 const int increment = 100;
10
11 void Stash::initialize(int sz) {
12 size = sz;
13 quantity = 0;
14 storage = 0;
15 next = 0;
16 }
17
18 int Stash::add(const void* element) {
19 if(next >= quantity) // Enough space left?
20 inflate(increment);
21 // Copy element into storage,
22 // starting at next empty space:
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 153
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
23 int startBytes = next * size;
24 unsigned char* e = (unsigned char*)element;
25 for(int i = 0; i < size; i++)
26 storage[startBytes + i] = e[i];
27 next++;
28 return(next - 1); // Index number
29 }
30
31 void* Stash::fetch(int index) {
32 // Check index boundaries:
33 assert(0 <= index);
34 if(index >= next)
35 return 0; // To indicate the end
36 // Produce pointer to desired element:
37 return &(storage[index * size]);
38 }
39
40 int Stash::count() {
41 return next; // Number of elements in CStash
42 }
43
44 void Stash::inflate(int increase) {
45 assert(increase > 0);
46 int newQuantity = quantity + increase;
47 int newBytes = newQuantity * size;
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 154
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
48 int oldBytes = quantity * size;
49 unsigned char* b = new unsigned char[newBytes];
50 for(int i = 0; i < oldBytes; i++)
51 b[i] = storage[i]; // Copy old to new
52 delete [ ]storage; // Old storage
53 storage = b; // Point to new memory
54 quantity = newQuantity;
55 }
56
57 void Stash::cleanup() {
58 if(storage != 0) {
59 cout << "freeing storage" << endl;
60 delete [ ]storage;
61 }
62 }
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 155
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
POO b´asica (cont.)
• Adentro de las funciones miembro no es necesario dereferenciar al objeto
para obtener los miembros size, quantity. Es decir en vez de aparecer
s->size ahora s´olo aparece size, lo que ocurre es que al llamar
s1.initialize() la variable size corresponde al del objeto s1.
• Si uno necesita conocer el puntero a la estructura en la que estoy en este
momento se usa el keyword this que es un puntero al objeto en el que
estamos parados
1 void Stash::initialize(int sz) {
2 cout << "this: " << this << endl;
3 . . .
4 }
5
6 Stash s1;
7 cout << "&s1: " << &s1 << endl;
8 s1.initialize();
Imprimen el mismo puntero.
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 156
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
POO b´asica (cont.)
1 // Test of C++ library
2 #include "CppLib.h"
3 #include ". ./require.h"
4 #include <fstream>
5 #include <iostream>
6 #include <string>
7 using namespace std;
8
9 int main() {
10 Stash intStash;
11 intStash.initialize(sizeof(int));
12 for(int i = 0; i < 100; i++)
13 intStash.add(&i);
14 for(int j = 0; j < intStash.count(); j++)
15 cout << "intStash.fetch(" << j << ") = "
16 << *(int*)intStash.fetch(j)
17 << endl;
18 // Holds 80-character strings:
19 Stash stringStash;
20 const int bufsize = 80;
21 stringStash.initialize(sizeof(char) * bufsize);
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 157
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
22 ifstream in("CppLibTest.cpp");
23 assure(in, "CppLibTest.cpp");
24 string line;
25 while(getline(in, line))
26 stringStash.add(line.c-str());
27 int k = 0;
28 char* cp;
29 while((cp =(char*)stringStash.fetch(k++)) != 0)
30 cout << "stringStash.fetch(" << k << ") = "
31 << cp << endl;
32 intStash.cleanup();
33 stringStash.cleanup();
34 }
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 158
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
POO b´asica (cont.)
• Las llamadas a funciones de la librer´ıa se convierten as´ı
1 CStash-initialize(&s1,sz);
2 s1.initialize(size);
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 159
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Inclusion de headers
• Algunos headers pueden incluir a otros, por ejemplo el header de una
librer´ıa lib1.h puede incluir iostream. Entonces si otra librer´ıa lib2.h
tambi´en incluye iostream, al querer incluir a las dos librer´ıas
1 #include <lib1.h>
2 #include <lib2.h> // Incluye iostream 2 veces -> error
• No hay problema con las funciones, pero si con las estructuras (y clases).
• Se utiliza un mecanismo con macros para evitar la doble inclusi´on.
Podemos usar los macros para incluir condicionalmente partes del
c´odigo.
1 #define FLAG
2
3 #ifdef FLAG
4 //. . .
5 #else
6 //. . .
7 #endif
Notar que es muy diferente este condicional del preprocesador que el
if-else de C++. En el del preprocesador s´olo uno de los bloques se
compila. Quiere decir que se puede usar para usar diferentes pedazos de
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 160
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
c´odigo que de otra forma no compilar´ıa. Por ejemplo
1 #ifdef HAS-PETSC
2 //. . . Version que usa la libreria PETSC
3 #else
4 //. . . Version alternativa
5 #endif
• El macro se puede definir usando un #define FLAG como arriba, o tambi´en
al compilar usando $$ g++ -DFLAG ...
• Lo contrario de definir un macro es hacerlo indefinido con #undef FLAG, a
partir de ahi #ifdef FLAG da falso.
• #undef se puede usar para redefinir macros
1 #define MAX-SIZE 100
2 . . . .
3 #define MAX-SIZE 1000 // -> Error
1 #define MAX-SIZE 100
2
3 . . .
4 #undef MAX-SIZE
5 #define MAX-SIZE 1000 // OK!
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 161
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Inclusion de headers (cont.)
• Para evitar la doble inclusi´on se utiliza un macro de protecci´on
1 #ifndef STASH-H
2 #define STASH-H
3 // Type declaration here. . .
4 #endif // STASH-H
• Ahora si se incluye dos veces el header no hay problema, ya que la
segunda vez en realidad no es incluido.
1 #include <stash.h>
2 #include <stash.h> // no es incluido esta vez!!
• El macro centinela STASH_H debe ser ´unico para ese archivo. Si otro
archivo usa el mismo macro centinela entonces sus declaraciones no son
incluidas
1 #include <libreria1/stash.h>
2 #include <libreria2/stash.h> // Error: este no es incluido
Deberian usar LIBRERIA1_STASH_H y LIBRERIA2_STASH_H.
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 162
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Inclusion de headers (cont.)
• Si en un header mylib.h se utilizan elementos de iostream es tentador
poner un using namespace std; en el header, para no tener que andar
poniendo el namespace std expl´ıcitamente (e.g. std::cout).
• Lamentablemente esto producir´ıa que si un usuario incluye mylib.h todo
su c´odigo pierde la protecci´on del namespace y volvemos a la situaci´on
que quer´ıamos impedir con los namespace: la colisi´on de nombres.
• Por lo tanto la regla es: NO usar using namespace.. en los headers, s´olo en
los .cpp
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 163
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Estructuras enlazadas
• La siguiente estructura Stack representa una pila implementada con
celdas enlazadas. Las celdas son de otra estructura llamada Link que
contiene el dato data y un puntero a la siguiente celda next.
1 struct Link {
2 void* data;
3 Link* next;
4 void initialize(void* dat, Link* nxt);
5 };
Stack S
nextdata
head
nextdata nextdata nextdata
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 164
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Estructuras enlazadas (cont.)
1 struct Link {
2 void* data;
3 Link* next;
4 void initialize(void* dat, Link* nxt);
5 };
6
7 struct Stack {
8 Link *head;
9 void initialize();
10 void push(void* dat);
11 void* peek();
12 void* pop();
13 void cleanup();
14 };
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 165
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Estructuras enlazadas (cont.)
• La funci´on push() mete un nuevo elemento en la pila, peek() retorna un
puntero al elemento en el tope de la pila. pop() elimina un elemento del
tope. initialize() y cleanup() son como antes: se encargan de la
inicializaci´on y destrucci´on de la estructura.
• El tipo de las celdas Link s´olo se usar´a con la clase Stack. Si nuestra
librer´ıa quiere adem´as definir un tipo Queue que representa una cola, con
celdas enlazadas, entonces no podr´a usar el mismo nombre Link para sus
celdas.
• Para evitar esta colisi´on ponemos la clase Link adentro de la clase Stack
1 struct Stack {
2 struct Link {
3 void* data;
4 Link* next;
5 void initialize(void* dat, Link* nxt);
6 } *head;
7 void initialize();
8 void push(void* dat);
9 void* peek();
10 void* pop();
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 166
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
11 void cleanup();
12 };
• Notar que al definir el tipo Link en la misma declaraci´on del tipo se define
un puntero Link *head a la primera celda. Por supuesto se puede hacer
por separado tambi´en
1 struct Link {
2 . . .
3 };
4 Link *head;
Por eso las definiciones de estructuras struct Type {...}; terminan en un
punto y coma, ya que all´ı se pueden definir objetos de tipo Type al mismo
tiempo que se define el nuevo tipo.
• Notar que cada estructura Stack y Link tienen su funci´on de inicializaci´on
initialize().
• Link no tiene cleanup(), el mismo usario es responsable de liberar el
espacio apuntado por data, si existe.
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 167
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Estructuras enlazadas (cont.)
1 // Linked list with nesting
2 #include "Stack.h"
3 #include ". ./require.h"
4 using namespace std;
5
6 void
7 Stack::Link::initialize(void* dat, Link* nxt) {
8 data = dat;
9 next = nxt;
10 }
11
12 void Stack::initialize() { head = 0; }
13
14 void Stack::push(void* dat) {
15 Link* newLink = new Link;
16 newLink->initialize(dat, head);
17 head = newLink;
18 }
19
20 void* Stack::peek() {
21 require(head != 0, "Stack empty");
22 return head->data;
23 }
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 168
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
24
25 void* Stack::pop() {
26 if(head == 0) return 0;
27 void* result = head->data;
28 Link* oldHead = head;
29 head = head->next;
30 delete oldHead;
31 return result;
32 }
33
34 void Stack::cleanup() {
35 require(head == 0, "Stack not empty");
36 }
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 169
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Estructuras enlazadas (cont.)
Uso de Stack
1 // Test of nested linked list
2 #include "Stack.h"
3 #include ". ./require.h"
4 #include <fstream>
5 #include <iostream>
6 #include <string>
7 using namespace std;
8
9 int main(int argc, char* argv[ ]) {
10 requireArgs(argc, 1); // File name is argument
11 ifstream in(argv[1]);
12 assure(in, argv[1]);
13 Stack textlines;
14 textlines.initialize();
15 string line;
16 // Read file and store lines in the Stack:
17 while(getline(in, line))
18 textlines.push(new string(line));
19 // Pop the lines from the Stack and print them:
20 string* s;
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 170
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
21 while((s = (string*)textlines.pop()) != 0) {
22 cout << *s << endl;
23 delete s;
24 }
25 textlines.cleanup();
26 }
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 171
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
M´as sobre scoping
Si existen varias versiones de variables con un mismo nombre, la que se ve
es la del scope mas interno. Se puede acceder a las otras utilizando el
operador de scope apropiado. Para las globales hay que usar el scop :: (sin
nada a la izquierda).
1 // Global scope resolution
2 int a;
3 void f() {}
4
5 struct S {
6 int a;
7 void f();
8 };
9
10 void S::f() {
11 ::f(); // Would be recursive otherwise!
12 ::a++; // Select the global a
13 a--; // The a at struct scope
14 }
15 int main() { S s; f(); }
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 172
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Tipos Abstractos de Datos (ADT)
Con este ejemplo hemos visto una idea fundamental de C++ que es incluir
funciones adentro de las estructuras. Este nuevo tipo de estructura es
llamado un Tipo Abstracto de Datos (Abstract Data Type, ADT)). Las variables
de estos tipos se llaman objetos. Llamar una funci´on de la estructura sobre
un objeto es mandarle un mensaje al objeto.
Si bien encapsular datos y funciones en un TAD es un beneficio considerable
para organizar el c´odigo y prevenir la colisi´on de nombres, la OOP
(Programaci´on Orientada a Objetos) es mucho m´as que esto.
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 173
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Ocultando la implementaci´on
Una librer´ıa t´ıpica de C consiste de una o m´as definiciones de estructuras
(struct) y funciones asociadas que act´uan sobre dichas estructuras. En C++
las funciones se pueden asociar expl´ıcitamente a esas estructuras poniendo
sus declaraciones dentro del scope de la estructura.
Pero hay una cuesti´on adicional que es hasta donde el programador debe
permitir que el usuario de la librer´ıa manipule a la estructura. Si el usuario lee
las definiciones de la estructura puede por s´ı mismo manipular la estructura.
Ahora bien, si en alg´un momento el programador cambia la forma en que est´a
armada la estructura el c´odigo del usuario dejar´a de funcionar (“breaks the
code”).
Por ejemplo en la estructura Stack definida previamente el programador
podr´ıa en el futuro decidir que es mejor alocar la memoria de a grandes
chunks de 100 elementos o m´as que alocar de a uno como est´a hecho en esa
implementaci´on. Si el c´odigo del usuario depende de que la alocaci´on se
haga de a un elemento, entonces al producirse el cambio de implementaci´on
su c´odigo dejar´a de funcionar.
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 174
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Ocultando la implementaci´on (cont.)
En C esto se puede resolver parcialmente si el programador especifica en la
documentaci´on de la librer´ıa las funciones con las cuales el usuario de la
estructura debe manipular los objetos a trav´es de las funciones provistas, y
hasta que punto puede usar directamente los datos almacenados en la
estructura. Pero esto es s´olo un pacto entre el usuario y el programador, el
compilador no tiene forma de conocer estas reglas y prevenir al usuario de
manipular los objetos indebidamente.
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 175
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Control de acceso a los miembros
El acceso a los miembros de una estructura en C++ se hace a trav´es de 3
especificadores de acceso public, private y protected.
El keyword public quiere decir que todos los miembros siguientes son
accesibles para cualquiera, como ocurre con los miembros de una struct por
defecto. Por lo tanto, en el caso de una struct da lo mismo poner public al
principio o no. Las dos declaraciones siguientes son por lo tanto equivalentes
1 struct A {
2 int i,j;
3 float f;
4 void func();
5 };
6
7 struct A {
8 public:
9 int i,j;
10 float f;
11 void func();
12 };
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 176
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Control de acceso a los miembros (cont.)
La clave keyword private por el contrario, indica que los miembros
correspondientes s´olo se pueden acceder desde c´odigo (es decir funciones)
de la misma clase.
1 struct B {
2 private:
3 char j;
4 float f;
5 public:
6 int i;
7 void func();
8 };
9
10 void B::func() {
11 i = 0;
12 j = ’0’; // OK, access from a B function member
13 f = 0.0; // OK, idem
14 };
15
16 int main() {
17 B b;
18 b.i = 1; // OK, public
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 177
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
19 b.func(); // OK, public
20 b.j = ’1’; // Illegal, private
21 b.f = 1.0; // Illegal, private
22 }
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 178
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Control de acceso a los miembros (cont.)
• B::func() puede acceder a los miembros privados, porque es una funcion
de la clase, independientemente de si func() es a su vez privada o publica.
• Una vez que se incluye el keyword private todas las declaraciones de
miembros dato y funciones son privadas, hasta la siguiente keyword
public.
• Se pueden incluir tantas declaraciones private y public como sea
necesario.
• Se pueden incluir dos declaraciones private o public seguidas.
• protected es una mezcla de los dos, pero ser´a explicado m´as adelante
cuando se explique el concepto de herencia.
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 179
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Amistad (Friendship)
El keyword friend permite declarar que una funci´on que no es miembro de la
estructura tenga acceso a todos los miembros de la misma.
1 // Declaration (incomplete type specification):
2 struct X;
3
4 struct Y {
5 void f(X*);
6 };
7
8 struct X { // Definition
9 private:
10 int i;
11 public:
12 void initialize();
13 friend void g(X*, int); // Global friend
14 friend void Y::f(X*); // Struct member friend
15 friend struct Z; // Entire struct is a friend
16 friend void h();
17 };
18
19 void X::initialize() {
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 180
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
20 i = 0;
21 }
22
23 void g(X* x, int i) {
24 x->i = i;
25 }
26
27 void Y::f(X* x) {
28 x->i = 47;
29 }
30
31 struct Z {
32 private:
33 int j;
34 public:
35 void initialize();
36 void g(X* x);
37 };
38
39 void Z::initialize() {
40 j = 99;
41 }
42
43 void Z::g(X* x) {
44 x->i += j;
45 }
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 181
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
46
47 void h() {
48 X x;
49 x.i = 100; // Direct data manipulation
50 }
51
52 int main() {
53 X x;
54 Z z;
55 z.g(&x);
56 }
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 182
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Anidamiento (nesting) y amistad
El est´andar dice que en principio una clases anidada no tienen que ser
necesariamente amiga de la clase externa.
1 struct E {
2 private:
3 int x;
4 struct B { };
5 struct I {
6 private:
7 B b; // error1: E::B is private
8 int y;
9 void f(E* p, int i) {
10 p->x = i; // error2: E::x is private
11 }
12 };
13 int g(I* p) { return p->y; } // error3: I::y is private
14 };
Sin embargo en la pr´actica el GCC da acceso a la clase externa a la clase
interna, pero no al rev´es. Es decir da error en 1 y 2, pero no en 3.
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 183
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Object layout
Una de las condiciones de dise˜no de C++ fue que c´odigo v´alido en C deber´ıa
compilar sin problemas en C++. Por esto las construcciones de tipo struct
tienen a todos sus miembros p´ublicos.
Cuando el compilador organiza los datos dentro del objeto los guarda en
memoria en forma contigua, en el orden en el que est´an en la estructura.
Cuando introducimos especificadores de acceso, cada bloque de acceso
guarda sus miembros en forma contigua, pero los bloques de acceso pueden
estar entre s´ı puestos de cualquier forma (como si cada uno fuera una
estructura).
Las cuestiones de privilegios de acceso (acceso a los miembros privados y
p´ublicos de la clase) tiene sentido s´olo en el momento de compilaci´on. Una
vez que el c´odigo fuente es convertido a c´odigo de m´aquina dos estructuras
que difieren s´olo en cuanto a sus secciones private y public son
indistinguibles entre s´ı, a menos del efecto discutido previamente de la
disposici´on en la memoria (object layout).
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 184
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Clases
Controlar el acceso a los miembros de una estructura es parte de lo que se
llama “ocultar la implementaci´on” (implementation hiding). Esto es un
concepto clave en OOP.
En OOP se trata de ocultar lo m´as posible los miembros de la estructura, por
eso lo deseable ser´ıa que todos los miembros fueran privados por defecto.
Por eso en C++ existe un tipo de estructura alternativo class que es
completamente equivalente a las struct de C, pero donde todos los miembros
son por defecto private.
Todas estas clases son equivalentes
1 class A {
2 int i,j,k;
3 public:
4 double z;
5 void f();
6 };
7
8 struct B {
9 private:
10 int i,j,k;
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 185
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
11 public:
12 double z;
13 void f();
14 };
15
16 struct C {
17 double z; // salvo por el object layout
18 void f();
19 private:
20 int i,j,k;
21 };
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 186
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Clases (cont.)
Vemos la clase Stash ahora con control de acceso. Todos los datos son
privados. La funci´on inflate() tambi´en ya que s´olo es usada internamente.
1 class Stash {
2 int size; // Size of each space
3 int quantity; // Number of storage spaces
4 int next; // Next empty space
5 // Dynamically allocated array of bytes:
6 unsigned char* storage;
7 void inflate(int increase);
8 public:
9 void initialize(int size);
10 void cleanup();
11 int add(void* element);
12 void* fetch(int index);
13 int count();
14 };
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 187
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Clases (cont.)
En Stack ahora hacemos que toda la estructura Link sea privada o sea s´olo es
accesible desde las funciones miembro de Stack.
1 class Stack {
2 struct Link {
3 void* data;
4 Link* next;
5 void initialize(void* dat, Link* nxt);
6 }* head;
7 public:
8 void initialize();
9 void push(void* dat);
10 void* peek();
11 void* pop();
12 void cleanup();
13 };
Notar que Link sigue siendo declarada como struct. De todas formas toda la
estructura es privada, o sea que desde fuera de Stack no se puede acceder.
Podr´ıamos tambi´en declararla como clase, pero entonces deber´ıamos
declarar friend a Stack.
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 188
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Ocultando totalmente la implementaci´on
Todav´ıa uno podr´ıa preguntarse si se puede ocultar a´un m´as la
implementaci´on. Que el usuario vea s´olo la parte p´ublica. Otra raz´on es evitar
la recompilaci´on innecesaria. Una soluci´on es usar punteros opacos, (aka
handles, en C++ se usa tambi´en el nombre Cheshire’s cat). Por ejemplo
podr´ıamos ocultar completamente los detalles de Stash como est´a abajo. El
usuario s´olo tiene acceso a stashwrapper.h.
1 // Header file stashwrapper.h
2 class StashWrapper {
3 class Stash;
4 Stash *stash;
5 public:
6 void initialize(int size);
7 void cleanup();
8 int add(void* element);
9 void* fetch(int index);
10 int count();
11 };
12
13 // Implementation file stashwrapper.cpp
14 #include "stash.h"
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 189
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
15 void StashWrapper::initialize(int size) {
16 stash=new Stash;
17 stash->initialize();
18 }
19
20 void StashWrapper::cleanup() {
21 stash->cleanup();
22 delete stash;
23 }
24
25 int StashWrapper::add(void* element) {
26 stash->add(element);
27 }
28
29 //. . .
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 190
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Inicializaci´on y cleanup
Uno de los errores m´as comunes cuando se utilizan librer´ıas es no inicializar
y destruir (cleanup) apropiadamente los objetos. En las librer´ıas que hemos
descripto hasta ahora esto se hac´ıa con funciones initialize() y cleanup().
Una de las ideas que C++ toma de la OOP es que estas operaciones de
inicializaci´on y cleanup se hagan en forma autom´atica.
1 class A {
2 // . . .
3 };
4
5 void f() {
6 A a; // a is created -> do initialization
7 // Usar a . . .
8 // . . .
9 // . . .
10 } // a is destroyed -> do cleanup
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 191
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Inicializaci´on y cleanup (cont.)
Para esto debe haber dos funciones (una de inicializaci´on y otra de cleanup)
que tengan nombres especiales ya que deben ser llamadas autom´aticamente
por el compilador. En C++ estas funciones se llaman el constructor y el
destructor de la clase. El constructor tiene el mismo nombre que la clase y
puede tener argumentos
1 class A {
2 public:
3 A() { /*. . .*/ }
4 // . . .
5 };
6
7 void f() {
8 A a; // a is created -> calls ctor A::A()
9 // Usar a . . .
10 // . . .
11 }
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 192
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
El constructor
• El ctor puede tener argumentos y puede haber varios constructores. Cual
de ellos es utilizado depende del contexto en el que es llamado.
• El ctor que no tiene argumentos se llama el constructor por defecto.
• No retorna ning´un valor.
• Debe ser declarado public para que pueda ser utilizado.
• Puede ser privado pero entonces al menos debe tener una clase amiga ya
que si no no se podr´ıa construir ning´un objeto de la clase.
• Si no declaramos ning´un constructor entonces el compilador sintetiza
uno por nosotros y que es el constructor por defecto. Este ctor por
defecto no tiene cuerpo, lo ´unico que hace es llamar a los ctores por
defecto de cada uno de los miembros (si son clases).
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 193
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
El destructor
• Asi como el constructor garantiza que se llama a la rutina de
inicializaci´on, el destructor (abreviado dtor) se encarga de realizar las
tareas de cleanup.
• Es llamado autom´aticamente cuando termina el scope del objeto.
1 // Constructors & destructors
2 #include <iostream>
3 using namespace std;
4
5 class Tree {
6 int height;
7 public:
8 Tree(int initialHeight); // Constructor
9 ˜Tree(); // Destructor
10 void grow(int years);
11 void printsize();
12 };
13
14 Tree::Tree(int initialHeight) {
15 height = initialHeight;
16 }
17
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 194
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
18 Tree::˜Tree() {
19 cout << "inside Tree destructor" << endl;
20 printsize();
21 }
22
23 void Tree::grow(int years) {
24 height += years;
25 }
26
27 void Tree::printsize() {
28 cout << "Tree height is " << height << endl;
29 }
30
31 int main() {
32 cout << "before opening brace" << endl;
33 {
34 Tree t(12);
35 cout << "after Tree creation" << endl;
36 t.printsize();
37 t.grow(4);
38 cout << "before closing brace" << endl;
39 }
40 cout << "after closing brace" << endl;
41 } ///:˜
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 195
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
El destructor (cont.)
Salida del programa:
1 before opening brace
2 after Tree creation
3 Tree height is 12
4 before closing brace
5 inside Tree destructor
6 Tree height is 16
7 after closing brace
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 196
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Eliminaci´on del bloque de definici´on
Es t´ıpico de C tener que definir todas las variables al principio de un scope
(por ejemplo de una funci´on). Por el contrario C++ promueve que las variables
se definan lo m´as cerca posible del punto en el que van a ser usadas. Esto se
pega con el uso autom´atico de constructores, ya que puede ser que el
compilador no tenga toda la informaci´on como para llamar al constructor.
1 // Defining variables anywhere
2 #include ". ./require.h"
3 #include <iostream>
4 #include <string>
5 using namespace std;
6
7 class G {
8 int i;
9 public:
10 G(int ii);
11 };
12
13 G::G(int ii) { i = ii; }
14
15 int main() {
16 cout << "initialization value? ";
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 197
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
17 int retval = 0;
18 cin >> retval;
19 require(retval != 0);
20 int y = retval + 3;
21 G g(y);
22 }
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 198
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Clase stash con ctor/dtor
1 // With constructors & destructors
2 class Stash {
3 int size; // Size of each space
4 int quantity; // Number of storage spaces
5 int next; // Next empty space
6 // Dynamically allocated array of bytes:
7 unsigned char* storage;
8 void inflate(int increase);
9 public:
10 Stash(int size);
11 ˜Stash();
12 int add(void* element);
13 void* fetch(int index);
14 int count();
15 };
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 199
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Clase stash con ctor/dtor (cont.)
1 //: C06:Stash2.cpp {O}
2 // Constructors & destructors
3 #include "Stash2.h"
4 #include ". ./require.h"
5 #include <iostream>
6 #include <cassert>
7 using namespace std;
8 const int increment = 100;
9
10 Stash::Stash(int sz) {
11 size = sz;
12 quantity = 0;
13 storage = 0;
14 next = 0;
15 }
16
17 int Stash::add(void* element) {
18 if(next >= quantity) // Enough space left?
19 inflate(increment);
20 // Copy element into storage,
21 // starting at next empty space:
22 int startBytes = next * size;
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 200
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
23 unsigned char* e = (unsigned char*)element;
24 for(int i = 0; i < size; i++)
25 storage[startBytes + i] = e[i];
26 next++;
27 return(next - 1); // Index number
28 }
29
30 void* Stash::fetch(int index) {
31 require(0 <= index, "Stash::fetch (-)index");
32 if(index >= next)
33 return 0; // To indicate the end
34 // Produce pointer to desired element:
35 return &(storage[index * size]);
36 }
37
38 int Stash::count() {
39 return next; // Number of elements in CStash
40 }
41
42 void Stash::inflate(int increase) {
43 require(increase > 0,
44 "Stash::inflate zero or negative increase");
45 int newQuantity = quantity + increase;
46 int newBytes = newQuantity * size;
47 int oldBytes = quantity * size;
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 201
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
48 unsigned char* b = new unsigned char[newBytes];
49 for(int i = 0; i < oldBytes; i++)
50 b[i] = storage[i]; // Copy old to new
51 delete [ ](storage); // Old storage
52 storage = b; // Point to new memory
53 quantity = newQuantity;
54 }
55
56 Stash::˜Stash() {
57 if(storage != 0) {
58 cout << "freeing storage" << endl;
59 delete [ ]storage;
60 }
61 }
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 202
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Stack con ctor/dtor
1 // With constructors/destructors
2 #ifndef STACK3-H
3 #define STACK3-H
4
5 class Stack {
6 struct Link {
7 void* data;
8 Link* next;
9 Link(void* dat, Link* nxt);
10 ˜Link();
11 }* head;
12 public:
13 Stack();
14 ˜Stack();
15 void push(void* dat);
16 void* peek();
17 void* pop();
18 };
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 203
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Stack con ctor/dtor (cont.)
1 #include "Stack3.h"
2 #include ". ./require.h"
3 using namespace std;
4
5 Stack::Link::Link(void* dat, Link* nxt) {
6 data = dat;
7 next = nxt;
8 }
9
10 Stack::Link::˜Link() { }
11
12 Stack::Stack() { head = 0; }
13
14 void Stack::push(void* dat) {
15 head = new Link(dat,head);
16 }
17
18 void* Stack::peek() {
19 require(head != 0, "Stack empty");
20 return head->data;
21 }
22
23 void* Stack::pop() {
24 if(head == 0) return 0;
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 204
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
25 void* result = head->data;
26 Link* oldHead = head;
27 head = head->next;
28 delete oldHead;
29 return result;
30 }
31
32 Stack::˜Stack() {
33 require(head == 0, "Stack not empty");
34 } ///:˜
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 205
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Initializaci´on de agregados
• Agregados son arreglos, estructuras y clases. Arreglos son de elementos
de un solo tipo, estructuras y clases puede ser de elementos de diferente
tipo.
• Cuando se define un arreglo se puede inicializar con un juego de valores
entre llaves.
1 int a[5] = { 1, 2, 3, 4, 5 };
Inicializa cada uno de las posiciones de a en base a los valores entre
llaves.
• Inicializa el primero a partir de 17 y todos los dem´as a partir del
constructor por defecto
1 int b[6] = {17};
• Conteo autom´atico: autom´aticamente dimensiona c como c[4] a partir del
n´umero de elementos entre llaves.
1 int c[ ] = { 1, 2, 3, 4 };
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 206
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Inicializaci´on de estructuras
1 struct X {
2 int i;
3 float f;
4 char c;
5 };
6
7 X x1 = { 1, 2.2, ’c’ };
Se pueden inicializar un arreglo de X al mismo tiempo con doble llaves.
1 X x2[3] = { {1, 1.1, ’a’}, {2, 2.2, ’b’} };
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 207
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Sobrecarga de funciones
Vimos que el compilador decora los nombres de las funciones que
pertenecen a una clase (m´etodos) con el nombre de la clase
1 void f();
2 class X { void f(); };
Ac´a los nombres de las f no colisionan ya que son en realildad ::f() y X::f().
El compilador tambi´en decora los nombres de las funciones con el tipo de
sus argumentos de manera que
1 void print(char);
2 void print(float);
no colisionan entre s´ı. (En C esto dar´ıa un error.) Esto se llama sobrecargar el
nombre de la funci´on (en este caso print()). Sobrecargar quiere decir
entonces usar un mismo nombre para varias cosas diferentes.
Atenci´on: NO se puede sobrecargar funciones por el valor de retorno.
1 int f(char c,double x);
2 char f(char c,double x); // ERROR!
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 208
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Sobrecarga de funciones (cont.)
Si compilamos y corremos la utilidad nm al archivo objeto nos da el nombre
interno de la funci´on
1 [mstorti@galileo garage]$ nm try22.o
2 U --cxa-atexit
3 U --dso-handle
4 0000000000000010 T main
5 0000000000000000 T -Z1fcd <- This is int f(char c,double d)
El mangling _Z1fcd hace que el nombre del del archivo objeto sea ´unico. El
lenguaje C no hace mangling, por eso no se puede sobrecargar.
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 209
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Sobrecarga de funciones (cont.)
El nombre mangleado es dif´ıcil de identificar con respecto a la funci´on
original. La opci´on nm -C permite obtener un nombre m´as legible. Esto es muy
´util cuando queremos buscar si una librer´ıa tiene una dada funci´on o no. Por
otro lado el mangling puede depender del sistema y del compilador, lo cual va
en contra de la portabilidad. Es decir no es posible transferir una librer´ıa de
C++ compilado con un dado compilador a otro.
1 [mstorti@galileo garage]$ nm -C try22.o | grep f
2 00000000000002d4 t -GLOBAL--sub-I--Z1fcd
3 0000000000000000 T f(char, double)
4 [mstorti@galileo garage]$
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 210
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Sobrecarga de funciones (cont.)
Por lo tando, cuando definimos varios ctores, estamos sobrecargando el
nombre del ctor.
1 class Stash {
2 int size; // Size of each space
3 int quantity; // Number of storage spaces
4 int next; // Next empty space
5 // Dynamically allocated array of bytes:
6 unsigned char* storage;
7 void inflate(int increase);
8 public:
9 Stash(int size); // Zero quantity
10 Stash(int size, int initQuantity);
11 ˜Stash();
12 int add(void* element);
13 void* fetch(int index);
14 int count();
15 };
Ahora el ctor Stash(int,int) inicializa el tama˜no del stash a partir del segundo
argumento. En cambio recordemos que Stash(int) dejaba al stash vac´ıo.
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 211
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Argumentos por default
Otra posibilidad es que los dos ctores previos sean el mismo con un
argumento por default para el tama˜no
1 Stash(int size, int initQuantity = 0);
Entonces cuando se usa
1 Stash A(100), B(100, 2000);
En el primer llamado es equivalente a A(100,0)
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 212
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Constantes
Objetos de los cuales se supone que su valor no va a variar se pueden definir
como constantes
1 #define BUFSIZE 100 // en C
2 const int bufsize = 100; // en C++ (preferible)
En el caso de querer ponerlo en un header hay que usar
1 extern const int bufsize; // en un header
2 . . .
3 const int bufsize = 100; // en el .cpp
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 213
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Constantes (cont.)
Otro uso de const es para prometerle al compilador que no se va a modificar
esa variable, especialmente con punteros
1 const int* u;
Declara que u es un puntero a un int que es constante. De manera que si el
compilador detecta que estamos modificando al entero apuntado dar´a un
error
1 int x = 23;
2 const int* u;
3 u = &x;
4 *u = 55; // ERROR!
Notar que lo que es constante es el valor apuntado, no el puntero en si
mismo, el cual es modificado al hacer u = &x. Si queremos que el puntero sea
constante entonces hay que hacer
1 int x = 23, z=45;
2 int* const u = &x;
3 u = &z; // ERROR!
4 *u = 55; // OK, modifica x
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 214
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Constantes (cont.)
Tambi´en pueden ser constantes las dos cosas, el puntero y el objeto
1 const int x = 32;
2 const int* const u = &x;
C/C++ chequea los tipos, tambien la constancia
1 int d = 1;
2 const int e = 2;
3 int* u = &d; // OK -- d not const
4 int* v = &e; // ERROR! -- e const
5 int* w = (int*)&e; // Legal but bad practice
6 const int* z = &e; // OK
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 215
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Punteros a arreglos constantes de caracteres
1 char* cp = "Hello world"; // warning!!
Como el arreglo de caracteres no fue alocado con new, es constante, o sea
que debe ser declarado as´ı
1 const char* cp = "Hello world"; // OK
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 216
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Const en argumentos de funciones
1 void f(const int i) {
2 i++; // Illegal -- compile-time error
3 }
De todas formas no tiene demasiado sentido porque i es pasado por copia.
Pero s´ı tiene sentido cuando se pasan argumentos por referencia o por
puntero
1 void f(const int *p) {
2 *p = 23; // ERROR!
3 }
4
5 void g(const int &x) {
6 x = 23; // ERROR!
7 }
Recordar que pasar por puntero o referencia puede ser para modificar el valor
o tambi´en para evitar la copia. Incluyendo el const permite pasar los
argumentos en forma eficiente, pero evitando que accidentalmente se
modifique el objeto.
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 217
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Const en clases
Si se quiere tener par´ametros de una clase, que son constantes, entonces no
s´olo hay que ponerle const, sino tambi´en static que quiere decir que ese
miembro es el mismo para todos los objetos de la clase. De esa forma act´ua
como una variable global pero protegida por el scope de la clase. Sirve para
definir opciones de la clase para poder ser inspeccionadas o modificadas por
el usuario.
1 class StringStack {
2 static const int size = 100;
3 const string* stack[size];
4 int index;
5 public:
6 StringStack();
7 void push(const string* s);
8 const string* pop();
9 };
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 218
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Objetos const y funciones de la clase
Si tenemos una clase A entonces al declarar funciones as´ı
1 void f(const A &a);
2 void g(const A *p);
estamos diciendo que no van a modificar el argumento correspondiente.
¿Como hacer lo mismo con los m´etodos de la clase para decir que no
modifican al objeto que son aplicados (*this)?
1 class A {
2 public:
3 void f() const;
4 void g();
5 };
6 void A::f() const { /* . . . */ }
Quiere decir que si hacemos
1 A a;
2 a.f();
podemos estar seguros que la llamada a f() no modifica a a.
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 219
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Objetos const y funciones de la clase (cont.)
Entonces el compilador chequea que si un objeto es const s´olo pueden ser
llamados sobre el funciones y m´etodos que no lo modifican, es decir que lo
declaran const.
1 const A a1;
2 a1.f(); // OK, f es const
3 a1.g(); // ERROR, g no es const
4
5 void h(A &a) {
6 a.g(); // OK a no es const
7 }
8
9 void h2(const A &a) {
10 a.f(); // OK, f es const
11 a.g(); // ERROR, g no es const
12 }
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 220
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Chapter 5
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 221
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Funciones inline
• Cada vez que hay una llamada a funci´on hay un costo adicional de pasar
los argumentos por el stack a la funci´on y hacer un jump de assemble.
Para evitar esto podemos usar el keyword inline que indica al compilador
que queremos que el c´odigo de esa funci´on sea replicado en cada punto
en que lo llamamos.
• La ventaja, como dijimos, es la eficiencia, se evita el mecanismo de
llamado a funci´on en assemble.
• La desventaja es que el c´odigo binario de la funci´on aparece duplicado en
cada punto, con lo cual el ejecutable se hace m´as grande. Tambi´en
implica que el c´odigo de la funci´on debe ser visible (o sea estar en el
header) en cada punto en que queremos que sea implementado inline.
• El keyword inline es una sugerencia para el compilador. El compilador
puede despu´es hacer la funci´on realmente inline o no. A veces puede
hacerla no inline porque es muy compleja (e.g. tiene lazos) o porque en
alg´un punto se toma la direcci´on de la funci´on.
• Funciones definidas en la misma clase (y por lo tanto en el header
normalmente) son candidatas a ser promovidas a inline por el compilador.
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 222
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Funciones inline (cont.)
1 // file: a.hpp
2 // ‘max’ es explicitamente inline
3 // (Notar que si no es inline daria error
4 // al linkeditar por multiple definicion de max())
5 inline double max(double x,double y) {
6 return (x>y ? x : y);
7 }
8
9 class A {
10 private:
11 int maxsize;
12 public:
13 // Accessors: automaticamente inline
14 int get-maxsize() { return maxsize; }
15 void set-maxsize(int maxsz) { maxsize=maxsz; }
16 //. . .
17 };
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 223
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Funciones inline (cont.)
Otra forma que habr´ıa para evitar el llamado a funciones ser´ıa no definir la
funci´on sino que en cada punto que se usa incluir expl´ıcitamente su c´odigo.
Para evitar esto una forma que exist´ıa en C para crear las funciones inline era
definir macros, por ejemplo
1 #define MAX(x,y) (x>y ? x : y)
Recordar que eso hace que en cada punto del c´odigo final se reemplaze la
llamada a MAX por la expansi´on del macro.
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 224
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Funciones inline (cont.)
• OJO, como pasa en general con los macros son peligrosos, Por ejemplo
1 int l = MAX(j++,k);
tiene el efecto indeseado que incrementa dos veces a j.
• Otro problema es con la precedencia de los operadores.
1 #define SQUARE(x) x*x
2 . . .
3 // Hace a=11!!
4 a = SQUARE(5+1)
ya que es completamente equivalente a
1 a = 5+1*5+1
La definici´on apropiada se obtiene protegiendo los argumentos con
par´entesis.
1 #define SQUARE(x) (x)*(x)
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 225
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Especificaciones de linkedicion
Cuando declaramos una funci´on, digamos
1 void f(int x, char c);
dijimos que internamente el compilador la decora (tambi´en se llama a esto
mangling) a, por ejemplo, _Z1fcd. Esto es a efectos de poder despu´es
sobrecargar la funci´on. Ahora bien, si queremos usar una librer´ıa de C,
entonces ´esta cuando fue compilada no hizo el mangling, y por lo tanto
cuando se va a linkeditar no la va a encontrar. Para eso hay que usar el
keyword extern al declarar la funci´on
1 extern "C" void f(int x, char c);
Esto le dice al compilador que no decore el nombre de esa funci´on. Notar que
por lo tanto esa funci´on no puede ser sobrecargada.
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 226
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Especificaciones de linkedicion (cont.)
Como las declaraciones de las librer´ıas estar´an en headers de esas librer´ıas,
como hacemos para ponerle un extern "C" a cada una de las funciones del
header? Basta con hacerlo externo al include
1 extern "C" {
2 #include <clibheader.h>
3 }
Muchos de los headers de librer´ıas de C importantes ya vienen con este tipo
de declaraciones de forma de poder ser llamados desde C++, por ejemplo
todas las de la libc.
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 227
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Referencias en C++
Vimos el concepto de referencia, b´asicamente son punteros inteligentes que
se autodereferencian.
Se pueden implementar funciones que modifican sus argumentos mediante
punteros
1 void inc(int *x) {
2 *x = *x + 1,
3 }
4 . . .
5 int a=2;
6 inc(&a); // hace a=3
pero son engorrosos porque hay que ir derereferenciando el puntero. Con
referencias es mucho mejor,
1 void inc(int &x) {
2 x = x + 1,
3 }
4 . . .
5 int a=2;
6 inc(a); // hace a=3
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 228
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Referencias en C++ (cont.)
Otro uso es para crear aliases locales para modificar una parte de un
contenedor m´as grande, por ejemplo un arreglo de varias dimensiones
(tambi´en puede ser con los contenedores de las STL)
1 class A {
2 // . . . .
3 void f(); // modifica a *this
4 };
5
6 // arreglo multidimensional de A’s
7 A av[100][100][100];
8 // Un elemento particular de av
9 int i,j,k;
10 //. . .
11 av[i][j][k].f();
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 229
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Referencias en C++ (cont.)
Si queremos manipular mucho a ese elemento particular de av entonces en
cada punto hay que poner av[i][j][k]. Si fuera un tipo simple, como un int o
un double, entonces podr´ıamos crear una copia local y despu´es pisar el valor
en av
1 // arreglo multidimensional de A’s
2 int v[100][100][100];
3 // Un elemento particular de av
4 int x = v[i][j][k];
5 // . . . hace calculos con x
6 // Pisa el valor en av
7 v[i][j][k] = x;
Pero si A es una clase complicada esto implica hacer una copia del objeto, lo
cual es ineficiente y incluso puede ser que no podamos hacer copias del
objeto.
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 230
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Referencias en C++ (cont.)
De nuevo, una posibilidad es usar macros
1 // arreglo multidimensional de A’s
2 A av[100][100][100];
3 // Un elemento particular de av
4 int i,j,k;
5 #define AIJK av[i][j][k]
6 //. . .
7 AIJK.f();
Como siempre, los macros son peligrosos y hay que tratar de no usarlos.
Adem´as cada vez que llamamos a AIJK estamos haciendo una cuenta con
i,j,k para encontrar la posici´on correspondiente en v.
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 231
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Referencias en C++ (cont.)
Una posibilidad es usar punteros
1 // arreglo multidimensional de A’s
2 A av[100][100][100];
3 // Un elemento particular de av
4 int i,j,k;
5 A *ap = &av[i][j][k];
6
7 ap->f();
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 232
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Referencias en C++ (cont.)
Esto es eficiente, y compacto pero hay que andar dereferenciando ap. Todav´ıa
mejor es usar referencias
1 // arreglo multidimensional de A’s
2 A av[100][100][100];
3 // Un elemento particular de av
4 int i,j,k;
5 A &a = av[i][j][k];
6
7 a.f();
Es eficiente, limpio, y a se manipula como un objeto m´as de la clase.
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 233
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Reglas para las referencias
• Las referencias deben ser inicializadas cuando son creadas
1 A &a = av[i][j][k]; // OK
2
3 A &a; // ERROR (No incluye inicializacion)
4 a = av[i][j][k];
• Una vez que una referencia apunta a un objeto, no se lo puede hacer
apuntar a otro
1 A &a = av[i][j][k];
2 a = av[l][m][n]; // compila OK, pero no reposiciona
3 // la referencia, simplemente hace
4 // una copia del elemento l,m,n al i,j,k
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 234
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Reglas para las referencias (cont.)
Lo que SI se puede hacer es ir creando referencias con el mismo nombre a
diferentes objetos
1 for (int i=0; i<N; i++) {
2 for (int j=0; j<N; j++) {
3 for (int k=0; k<N; k++) {
4 A &a = av[i][j][k];
5 // manipula av[i][j][k] a trav´es de a
6 }
7 }
8 }
• No se puede hacer una referencia a NULL.
• Hacer referencias es muy eficiente, igual que con punteros.
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 235
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Paso por referencia y por copia
Normalmente uno escribe el paso de argumentos por copia
1 void f(A a, B b) {. . .}
Esto es ineficiente y adem´as requiere que las clases A, B implementen el
constructor por copia A(A&), B(B&) (en general se le llama X(X&)).
1 class A {
2 //. . .
3 A(A&) { . . . } // Constructor por copia
4 };
Para evitar esto ya mencionamos que se puede pasar por referencia
1 void f(A &a, B &b) {. . .}
Si la funci´on no va a modificar los argumentos es todav´ıa mejor declarar a las
referencias como const
1 void f(const A &a,const B &b) {. . .}
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 236
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
El constructor por copia
• Vimos que al pasar objetos a funciones por copia se llama al constructor
por copia.
• Si la clase no define al constructor por copia el compilador sintetiza uno
por nosotros (haciendo copia bit-a-bit).
• Esto se llama una shallow copy (por contraposici´on con una deep copy) y
puede traer problemas, sobre todo si el objeto contiene punteros a ´areas
de almacenamiento din´amico alocados con new.
• O bien hay que implementar el constructor por copia haciendo la deep
copy o bien hay que prohibirlo declarando al constructor por copia
privado
1 class A {
2 private:
3 A(A&) {}
4 }
5
6 void f(A a) { // ERROR, llama al ctor por copia
7 }
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 237
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Sobrecarga de operadores
• Sobrecarga de operadores es simplemente un aditivo sint´actico (sintactic
sugar) para hacer llamadas a funciones de la clase en forma m´as
compacta.
• Los nombres de los operadores son operator@ donde @ puede ser algunos
de los operadores usuales, matem´aticos (+, -, *, /), de indexaci´on [], (),
incremento ++, --, acumulaci´on (+=, -=, *=, /=), l´ogicos ||, &&, etc...
• Hay operadores unarios y binarios. A veces el mismo operador puede ser
unario o binario dependiendo del contexto (por ejemplo *
(dereferenciaci´on como unario, producto como binario), +, -).
• Cu´al de los operadores es llamado y sobre que objetos es a veces un
poco dif´ıcil de discernir.
• Pueden ser m´etodos de la clase o pueden ser funciones globales
(declaradas friend)
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 238
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Sobrecarga de operadores (cont.)
En el caso de operadores unarios, el objeto al cual se aplica el operador pasa
a ser *this
1 class A {
2 A operator*(const A& right) { . . . } // producto (1)
3 };
4
5 class HandleToA {
6 A &operator*() { . . . } // dereferenciacion (2)
7 };
8
9 A a1, a2, a3;
10 HandleToA p;
11
12 a1 = a2*a3; // llama a (1) con *this = a2,
13 // right = a3 y el valor de retorno
14 // es asignado a a1
15 a1 = *p; // llama a (2) con *this = p
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 239
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Sobrecarga de operadores (cont.)
1 #include <iostream>
2 using namespace std;
3
4 class Integer {
5 int i;
6 public:
7 Integer(int ii) : i(ii) {}
8 const Integer
9 operator+(const Integer& rv) const {
10 cout << "operator+" << endl;
11 return Integer(i + rv.i);
12 }
13 Integer&
14 operator+=(const Integer& rv) {
15 cout << "operator+=" << endl;
16 i += rv.i;
17 return *this;
18 }
19 };
20
21 int main() {
22 cout << "built-in types:" << endl;
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 240
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
23 int i = 1, j = 2, k = 3;
24 k += i + j;
25 cout << "user-defined types:" << endl;
26 Integer ii(1), jj(2), kk(3);
27 kk += ii + jj;
28 }
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 241
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Sobrecarga de operadores (cont.)
• Se pueden sobrecargar buena parte de los operadores que ya existen en C.
• No se pueden inventar nuevos operadores (e.g. usar ** para la
exponenciaci´on, como en Fortran).
• No se puede cambiar la regla de precedencia de los operadores.
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 242
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Sobrecarga de operadores unarios
1 #include <iostream>
2 using namespace std;
3
4 // Non-member functions:
5 class Integer {
6 long i;
7 Integer* This() { return this; }
8 public:
9 Integer(long ll = 0) : i(ll) {}
10 // No side effects takes const& argument:
11 friend const Integer&
12 operator+(const Integer& a);
13 friend const Integer
14 operator-(const Integer& a);
15 friend const Integer
16 operator˜(const Integer& a);
17 friend Integer*
18 operator&(Integer& a);
19 friend int
20 operator!(const Integer& a);
21 // Side effects have non-const& argument:
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 243
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
22 // Prefix:
23 friend const Integer&
24 operator++(Integer& a);
25 // Postfix:
26 friend const Integer
27 operator++(Integer& a, int);
28 // Prefix:
29 friend const Integer&
30 operator--(Integer& a);
31 // Postfix:
32 friend const Integer
33 operator--(Integer& a, int);
34 };
35
36 // Global operators:
37 const Integer& operator+(const Integer& a) {
38 cout << "+Integern";
39 return a; // Unary + has no effect
40 }
41 const Integer operator-(const Integer& a) {
42 cout << "-Integern";
43 return Integer(-a.i);
44 }
45 const Integer operator˜(const Integer& a) {
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 244
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
46 cout << "˜Integern";
47 return Integer(˜a.i);
48 }
49 Integer* operator&(Integer& a) {
50 cout << "&Integern";
51 return a.This(); // &a is recursive!
52 }
53 int operator!(const Integer& a) {
54 cout << "bang Integern";
55 return !a.i;
56 }
57 // Prefix; return incremented value
58 const Integer& operator++(Integer& a) {
59 cout << "++Integern";
60 a.i++;
61 return a;
62 }
63 // Postfix; return the value before increment:
64 const Integer operator++(Integer& a, int) {
65 cout << "Integer++n";
66 Integer before(a.i);
67 a.i++;
68 return before;
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 245
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
69 }
70 // Prefix; return decremented value
71 const Integer& operator--(Integer& a) {
72 cout << "--Integern";
73 a.i--;
74 return a;
75 }
76 // Postfix; return the value before decrement:
77 const Integer operator--(Integer& a, int) {
78 cout << "Integer--n";
79 Integer before(a.i);
80 a.i--;
81 return before;
82 }
83
84 // Show that the overloaded operators work:
85 void f(Integer a) {
86 +a;
87 -a;
88 ˜a;
89 Integer* ip = &a;
90 !a;
91 ++a;
92 a++;
93 --a;
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 246
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
94 a--;
95 }
96
97 // Member functions (implicit ‘‘this’’):
98 class Byte {
99 unsigned char b;
100 public:
101 Byte(unsigned char bb = 0) : b(bb) {}
102 // No side effects: const member function:
103 const Byte& operator+() const {
104 cout << "+Byten";
105 return *this;
106 }
107 const Byte operator-() const {
108 cout << "-Byten";
109 return Byte(-b);
110 }
111 const Byte operator˜() const {
112 cout << "˜Byten";
113 return Byte(˜b);
114 }
115 Byte operator!() const {
116 cout << "bang Byten";
117 return Byte(!b);
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 247
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
118 }
119 Byte* operator&() {
120 cout << "&Byten";
121 return this;
122 }
123 // Side effects: non-const member function:
124 const Byte& operator++() { // Prefix
125 cout << "++Byten";
126 b++;
127 return *this;
128 }
129 const Byte operator++(int) { // Postfix
130 cout << "Byte++n";
131 Byte before(b);
132 b++;
133 return before;
134 }
135 const Byte& operator--() { // Prefix
136 cout << "--Byten";
137 --b;
138 return *this;
139 }
140 const Byte operator--(int) { // Postfix
141 cout << "Byte--n";
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 248
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
142 Byte before(b);
143 --b;
144 return before;
145 }
146 };
147
148 void g(Byte b) {
149 +b;
150 -b;
151 ˜b;
152 Byte* bp = &b;
153 !b;
154 ++b;
155 b++;
156 --b;
157 b--;
158 }
159
160 int main() {
161 Integer a;
162 f(a);
163 Byte b;
164 g(b);
165 } ///:˜
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 249
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Sobrecarga de operadores unarios (cont.)
Operadores ++ y -- prefijo y postfijo: Recordemos que hay dos versiones del
operador ++, cuando hacemos i++ y ++i, ambos se pueden sobrecargar con el
operador operator++() pero como hacer para diferenciarlos? El prefijo es
operator++() y el postfijo es operator++(int). Notar que el argumento int para
el postfijo no se usa y por lo tanto no hace falta pasarle el argumento dummy
correspondiente.
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 250
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Sobrecarga de operadores binarios
1 // Non-member overloaded operators
2 #include <iostream>
3
4 // Non-member functions:
5 class Integer {
6 long i;
7 public:
8 Integer(long ll = 0) : i(ll) {}
9 // Operators that create new, modified value:
10 friend const Integer
11 operator+(const Integer& left,
12 const Integer& right);
13 friend const Integer
14 operator-(const Integer& left,
15 const Integer& right);
16 friend const Integer
17 operator*(const Integer& left,
18 const Integer& right);
19 friend const Integer
20 operator/(const Integer& left,
21 const Integer& right);
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 251
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
22 friend const Integer
23 operator%(const Integer& left,
24 const Integer& right);
25 friend const Integer
26 operatorˆ(const Integer& left,
27 const Integer& right);
28 friend const Integer
29 operator&(const Integer& left,
30 const Integer& right);
31 friend const Integer
32 operator|(const Integer& left,
33 const Integer& right);
34 friend const Integer
35 operator<<(const Integer& left,
36 const Integer& right);
37 friend const Integer
38 operator>>(const Integer& left,
39 const Integer& right);
40 // Assignments modify & return lvalue:
41 friend Integer&
42 operator+=(Integer& left,
43 const Integer& right);
44 friend Integer&
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 252
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
45 operator-=(Integer& left,
46 const Integer& right);
47 friend Integer&
48 operator*=(Integer& left,
49 const Integer& right);
50 friend Integer&
51 operator/=(Integer& left,
52 const Integer& right);
53 friend Integer&
54 operator%=(Integer& left,
55 const Integer& right);
56 friend Integer&
57 operatorˆ=(Integer& left,
58 const Integer& right);
59 friend Integer&
60 operator&=(Integer& left,
61 const Integer& right);
62 friend Integer&
63 operator|=(Integer& left,
64 const Integer& right);
65 friend Integer&
66 operator>>=(Integer& left,
67 const Integer& right);
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 253
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
68 friend Integer&
69 operator<<=(Integer& left,
70 const Integer& right);
71 // Conditional operators return true/false:
72 friend int
73 operator==(const Integer& left,
74 const Integer& right);
75 friend int
76 operator!=(const Integer& left,
77 const Integer& right);
78 friend int
79 operator<(const Integer& left,
80 const Integer& right);
81 friend int
82 operator>(const Integer& left,
83 const Integer& right);
84 friend int
85 operator<=(const Integer& left,
86 const Integer& right);
87 friend int
88 operator>=(const Integer& left,
89 const Integer& right);
90 friend int
91 operator&&(const Integer& left,
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 254
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
92 const Integer& right);
93 friend int
94 operator| |(const Integer& left,
95 const Integer& right);
96 // Write the contents to an ostream:
97 void print(std::ostream& os) const { os << i; }
98 };
99 #endif // INTEGER-H ///:˜
100
101 //: C12:Integer.cpp {O}
102 // Implementation of overloaded operators
103 #include "Integer.h"
104 #include ". ./require.h"
105
106 const Integer
107 operator+(const Integer& left,
108 const Integer& right) {
109 return Integer(left.i + right.i);
110 }
111 const Integer
112 operator-(const Integer& left,
113 const Integer& right) {
114 return Integer(left.i - right.i);
115 }
116 const Integer
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 255
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
117 operator*(const Integer& left,
118 const Integer& right) {
119 return Integer(left.i * right.i);
120 }
121 const Integer
122 operator/(const Integer& left,
123 const Integer& right) {
124 require(right.i != 0, "divide by zero");
125 return Integer(left.i / right.i);
126 }
127 const Integer
128 operator%(const Integer& left,
129 const Integer& right) {
130 require(right.i != 0, "modulo by zero");
131 return Integer(left.i % right.i);
132 }
133 const Integer
134 operatorˆ(const Integer& left,
135 const Integer& right) {
136 return Integer(left.i ˆ right.i);
137 }
138 const Integer
139 operator&(const Integer& left,
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 256
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
140 const Integer& right) {
141 return Integer(left.i & right.i);
142 }
143 const Integer
144 operator|(const Integer& left,
145 const Integer& right) {
146 return Integer(left.i | right.i);
147 }
148 const Integer
149 operator<<(const Integer& left,
150 const Integer& right) {
151 return Integer(left.i << right.i);
152 }
153 const Integer
154 operator>>(const Integer& left,
155 const Integer& right) {
156 return Integer(left.i >> right.i);
157 }
158 // Assignments modify & return lvalue:
159 Integer& operator+=(Integer& left,
160 const Integer& right) {
161 if(&left == &right) {/* self-assignment */}
162 left.i += right.i;
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 257
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
163 return left;
164 }
165 Integer& operator-=(Integer& left,
166 const Integer& right) {
167 if(&left == &right) {/* self-assignment */}
168 left.i -= right.i;
169 return left;
170 }
171 Integer& operator*=(Integer& left,
172 const Integer& right) {
173 if(&left == &right) {/* self-assignment */}
174 left.i *= right.i;
175 return left;
176 }
177 Integer& operator/=(Integer& left,
178 const Integer& right) {
179 require(right.i != 0, "divide by zero");
180 if(&left == &right) {/* self-assignment */}
181 left.i /= right.i;
182 return left;
183 }
184 Integer& operator%=(Integer& left,
185 const Integer& right) {
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 258
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
186 require(right.i != 0, "modulo by zero");
187 if(&left == &right) {/* self-assignment */}
188 left.i %= right.i;
189 return left;
190 }
191 Integer& operatorˆ=(Integer& left,
192 const Integer& right) {
193 if(&left == &right) {/* self-assignment */}
194 left.i ˆ= right.i;
195 return left;
196 }
197 Integer& operator&=(Integer& left,
198 const Integer& right) {
199 if(&left == &right) {/* self-assignment */}
200 left.i &= right.i;
201 return left;
202 }
203 Integer& operator|=(Integer& left,
204 const Integer& right) {
205 if(&left == &right) {/* self-assignment */}
206 left.i |= right.i;
207 return left;
208 }
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 259
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
209 Integer& operator>>=(Integer& left,
210 const Integer& right) {
211 if(&left == &right) {/* self-assignment */}
212 left.i >>= right.i;
213 return left;
214 }
215 Integer& operator<<=(Integer& left,
216 const Integer& right) {
217 if(&left == &right) {/* self-assignment */}
218 left.i <<= right.i;
219 return left;
220 }
221 // Conditional operators return true/false:
222 int operator==(const Integer& left,
223 const Integer& right) {
224 return left.i == right.i;
225 }
226 int operator!=(const Integer& left,
227 const Integer& right) {
228 return left.i != right.i;
229 }
230 int operator<(const Integer& left,
231 const Integer& right) {
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 260
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
232 return left.i < right.i;
233 }
234 int operator>(const Integer& left,
235 const Integer& right) {
236 return left.i > right.i;
237 }
238 int operator<=(const Integer& left,
239 const Integer& right) {
240 return left.i <= right.i;
241 }
242 int operator>=(const Integer& left,
243 const Integer& right) {
244 return left.i >= right.i;
245 }
246 int operator&&(const Integer& left,
247 const Integer& right) {
248 return left.i && right.i;
249 }
250 int operator| |(const Integer& left,
251 const Integer& right) {
252 return left.i | | right.i;
253 } ///:˜
254
255 //: C12:IntegerTest.cpp
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 261
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
256 //{L} Integer
257 #include "Integer.h"
258 #include <fstream>
259 using namespace std;
260 ofstream out("IntegerTest.out");
261
262 void h(Integer& c1, Integer& c2) {
263 // A complex expression:
264 c1 += c1 * c2 + c2 % c1;
265 #define TRY(OP) 
266 out << "c1 = "; c1.print(out); 
267 out << ", c2 = "; c2.print(out); 
268 out << "; c1 " #OP " c2 produces "; 
269 (c1 OP c2).print(out); 
270 out << endl;
271 TRY(+) TRY(-) TRY(*) TRY(/)
272 TRY(%) TRY(ˆ) TRY(&) TRY(|)
273 TRY(<<) TRY(>>) TRY(+=) TRY(-=)
274 TRY(*=) TRY(/=) TRY(%=) TRY(ˆ=)
275 TRY(&=) TRY(|=) TRY(>>=) TRY(<<=)
276 // Conditionals:
277 #define TRYC(OP) 
278 out << "c1 = "; c1.print(out); 
279 out << ", c2 = "; c2.print(out); 
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 262
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
280 out << "; c1 " #OP " c2 produces "; 
281 out << (c1 OP c2); 
282 out << endl;
283 TRYC(<) TRYC(>) TRYC(==) TRYC(!=) TRYC(<=)
284 TRYC(>=) TRYC(&&) TRYC(| |)
285 }
286
287 int main() {
288 cout << "friend functions" << endl;
289 Integer c1(47), c2(9);
290 h(c1, c2);
291 } ///:˜
292
293 //: C12:Byte.h
294 // Member overloaded operators
295 #ifndef BYTE-H
296 #define BYTE-H
297 #include ". ./require.h"
298 #include <iostream>
299 // Member functions (implicit ‘‘this’’):
300 class Byte {
301 unsigned char b;
302 public:
303 Byte(unsigned char bb = 0) : b(bb) {}
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 263
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
304 // No side effects: const member function:
305 const Byte
306 operator+(const Byte& right) const {
307 return Byte(b + right.b);
308 }
309 const Byte
310 operator-(const Byte& right) const {
311 return Byte(b - right.b);
312 }
313 const Byte
314 operator*(const Byte& right) const {
315 return Byte(b * right.b);
316 }
317 const Byte
318 operator/(const Byte& right) const {
319 require(right.b != 0, "divide by zero");
320 return Byte(b / right.b);
321 }
322 const Byte
323 operator%(const Byte& right) const {
324 require(right.b != 0, "modulo by zero");
325 return Byte(b % right.b);
326 }
327 const Byte
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 264
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
328 operatorˆ(const Byte& right) const {
329 return Byte(b ˆ right.b);
330 }
331 const Byte
332 operator&(const Byte& right) const {
333 return Byte(b & right.b);
334 }
335 const Byte
336 operator|(const Byte& right) const {
337 return Byte(b | right.b);
338 }
339 const Byte
340 operator<<(const Byte& right) const {
341 return Byte(b << right.b);
342 }
343 const Byte
344 operator>>(const Byte& right) const {
345 return Byte(b >> right.b);
346 }
347 // Assignments modify & return lvalue.
348 // operator= can only be a member function:
349 Byte& operator=(const Byte& right) {
350 // Handle self-assignment:
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 265
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
351 if(this == &right) return *this;
352 b = right.b;
353 return *this;
354 }
355 Byte& operator+=(const Byte& right) {
356 if(this == &right) {/* self-assignment */}
357 b += right.b;
358 return *this;
359 }
360 Byte& operator-=(const Byte& right) {
361 if(this == &right) {/* self-assignment */}
362 b -= right.b;
363 return *this;
364 }
365 Byte& operator*=(const Byte& right) {
366 if(this == &right) {/* self-assignment */}
367 b *= right.b;
368 return *this;
369 }
370 Byte& operator/=(const Byte& right) {
371 require(right.b != 0, "divide by zero");
372 if(this == &right) {/* self-assignment */}
373 b /= right.b;
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 266
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
374 return *this;
375 }
376 Byte& operator%=(const Byte& right) {
377 require(right.b != 0, "modulo by zero");
378 if(this == &right) {/* self-assignment */}
379 b %= right.b;
380 return *this;
381 }
382 Byte& operatorˆ=(const Byte& right) {
383 if(this == &right) {/* self-assignment */}
384 b ˆ= right.b;
385 return *this;
386 }
387 Byte& operator&=(const Byte& right) {
388 if(this == &right) {/* self-assignment */}
389 b &= right.b;
390 return *this;
391 }
392 Byte& operator|=(const Byte& right) {
393 if(this == &right) {/* self-assignment */}
394 b |= right.b;
395 return *this;
396 }
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 267
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
397 Byte& operator>>=(const Byte& right) {
398 if(this == &right) {/* self-assignment */}
399 b >>= right.b;
400 return *this;
401 }
402 Byte& operator<<=(const Byte& right) {
403 if(this == &right) {/* self-assignment */}
404 b <<= right.b;
405 return *this;
406 }
407 // Conditional operators return true/false:
408 int operator==(const Byte& right) const {
409 return b == right.b;
410 }
411 int operator!=(const Byte& right) const {
412 return b != right.b;
413 }
414 int operator<(const Byte& right) const {
415 return b < right.b;
416 }
417 int operator>(const Byte& right) const {
418 return b > right.b;
419 }
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 268
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
420 int operator<=(const Byte& right) const {
421 return b <= right.b;
422 }
423 int operator>=(const Byte& right) const {
424 return b >= right.b;
425 }
426 int operator&&(const Byte& right) const {
427 return b && right.b;
428 }
429 int operator| |(const Byte& right) const {
430 return b | | right.b;
431 }
432 // Write the contents to an ostream:
433 void print(std::ostream& os) const {
434 os << "0x" << std::hex << int(b) << std::dec;
435 }
436 };
437 #endif // BYTE-H ///:˜
438
439 //: C12:ByteTest.cpp
440 #include "Byte.h"
441 #include <fstream>
442 using namespace std;
443 ofstream out("ByteTest.out");
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 269
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
444
445 void k(Byte& b1, Byte& b2) {
446 b1 = b1 * b2 + b2 % b1;
447
448 #define TRY2(OP) 
449 out << "b1 = "; b1.print(out); 
450 out << ", b2 = "; b2.print(out); 
451 out << "; b1 " #OP " b2 produces "; 
452 (b1 OP b2).print(out); 
453 out << endl;
454
455 b1 = 9; b2 = 47;
456 TRY2(+) TRY2(-) TRY2(*) TRY2(/)
457 TRY2(%) TRY2(ˆ) TRY2(&) TRY2(|)
458 TRY2(<<) TRY2(>>) TRY2(+=) TRY2(-=)
459 TRY2(*=) TRY2(/=) TRY2(%=) TRY2(ˆ=)
460 TRY2(&=) TRY2(|=) TRY2(>>=) TRY2(<<=)
461 TRY2(=) // Assignment operator
462
463 // Conditionals:
464 #define TRYC2(OP) 
465 out << "b1 = "; b1.print(out); 
466 out << ", b2 = "; b2.print(out); 
467 out << "; b1 " #OP " b2 produces "; 
468 out << (b1 OP b2); 
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 270
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
469 out << endl;
470
471 b1 = 9; b2 = 47;
472 TRYC2(<) TRYC2(>) TRYC2(==) TRYC2(!=) TRYC2(<=)
473 TRYC2(>=) TRYC2(&&) TRYC2(| |)
474
475 // Chained assignment:
476 Byte b3 = 92;
477 b1 = b2 = b3;
478 }
479
480 int main() {
481 out << "member functions:" << endl;
482 Byte b1(47), b2(9);
483 k(b1, b2);
484 } ///:˜
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 271
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Sobrecarga de operadores binarios (cont.)
• En los operadores de acumulaci´on (e.g. operator+=) se tiene que
1 Integer& operator+=(Integer& left,
2 const Integer& right) {
3 if(&left == &right) {/* self-assignment */}
4 left.i += right.i;
5 return left;
6 }
7 // . . .
8 Integer R,L;
9 L += R;
Tenemos que left es L, right es R. Hay que tener cuidado porque el L y R
podr´ıan ser el mismo objeto, por ejemplo si hacemos
1 Integer A;
2 A += A;
Lo mismo pasa con el operador de asignaci´on operator=(). A esto se le
llama chequear por autoasignaci´on. Sobre todo si hay componentes
apuntadas por punteros.
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 272
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Chapter
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 273
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Otros operadores que se pueden sobrecargar
• operator[]: Se usa normalmente para emular lo que ocurre al indexar un
vector por un entero. En las STL se usa en las clases vector<> y map<>
• operator(): Se usa para emular que el objeto act´ua como una funci´on
(functor).
• operator*, operator->: Se utilizan para emular el comportamiento de los
punteros (por ejemplo los smart pointers). En las STL se usan para los
iterators de los diferentes contenedores.
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 274
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Creaci´on din´amica de objetos
Las variables de un programa pueden ser alocados en tres formas diferentes
y normalmente viven en secciones diferentes de memoria
• Objetos globales y est´aticos son alocados en el momento de arrancar el
programa y viven durante toda la duraci´on del mismo.
• Objetos din´amicos son alocados al entrar en el scope correspondiente.
La alocaci´on se hace en el stack.
• Objetos pueden ser alocados y desalocados en cualquier momento
(responsabilidad del programador) en el heap.
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 275
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Uso de la memoria din´amica en C
En C la alocaci´on en el heap se hace con las funciones malloc() y free(). El
uso b´asico para objetos en C ser´ıa as´ı
1 struct A { };
2
3 A *p = (A*)malloc(sizeof(A));
4 A-initialize(p);
5 // . . . . usa *p
6 A-destroy(p);
7 free(p);
Hay varios puntos donde esto puede fallar, por un error del programador:
• No alocar apropiadamente la memoria apropiada para el objeto.
• No convertir el puntero al tipo apropiado.
• No inicializar el objeto.
• No destruir el objeto.
• No liberar la memoria alocada.
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 276
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Uso de la memoria din´amica en C++
En C++ se trata que todas estas acciones sean hechas en lo posible en forma
autom´atica por el operador. Para esto las funciones malloc() y free() (que
despu´es de todo son funciones de librer´ıa es decir que no son parte del
lenguaje) son reemplazadas por operadores intr´ınsecos del lenguaje: new y
delete.
1 A *p = new A;
2 // . . . usa *p
3 delete p;
new A se encarga de alocar el espacio apropiado (sizeof(A), castear al tipo
correcto (A*) e inicializar (llamar al constructor).
delete p se encarga de llamar al destructor y liberar la memoria alocada.
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 277
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Uso de la memoria din´amica en C++ (cont.)
Como new se encarga de la inicializaci´on, tambi´en se puede llamar con
cualquier otro constructor, adem´as del ctor por defecto
1 A *p = new A(x,y,z);
Tambi´en se pueden alocar arreglos de objetos
1 A *av = new A[100];
En este caso el compilador se encarga de alocar el espacio para los 100
objetos y llamar al constructor por defecto sobre cada uno de ellos. No hay
forma de inicializar arreglos con un constructor que no sea el ctor por defecto.
Recordar que para arreglos se puede inicializar expl´ıcitamente cada objeto
(pero no todos al mismo tiempo)
1 A av[4] = {1,2,3}
Para el cuarto (av[3]) usa el constructor por defecto.
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 278
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Porqu´e usar new y no arreglos
1 A av1[20]; // OK la dimension es una cte
2
3 const int m=100;
4 A av1[m]; // OK la dimension es una cte
5
6 int n=100;
7 A a[n]; // ERROR
El ´ultimo deber´ıa dar error de compilaci´on aunque dependiendo del
compilador puede que no lo de (ser´ıa una extensi´on del compilador). De
todas formas siempre es m´as restrictivo que alocar con new porque el arreglo
es desalocado y destruido cuando termina su scope.
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 279
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Memory exhaust
Qu´e ocurre si se acaba la memoria? En viejos compiladores new retornaba un
puntero nulo. En el est´andar actual lanza una excepci´on de tipo bad_alloc().
Por compatibilidad con la versi´on antigua se le puede usar new(std::nothrow)
que emula el primer comportamiento.
1 try { // version ‘throw’
2 int *p = new int[N];
3 // alocacion exitosa, usar p. . .
4 } catch(bad-alloc) {
5 cout << "error" << endl;
6 break;
7 }
8
9 // version ‘nothrow’
10 int *p = new(std::nothrow) int[N];
11 if (!p) {
12 // error. . .
13 }
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 280
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Composici´on
Hasta ahora vimos clases/estructuras que se construyen a partir de tipos
b´asicos usando composici´on.
1 class A {
2 private:
3 int i;
4 double x;
5 public:
6 char c;
7 void f();
8 };
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 281
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Composici´on (cont.)
La idea es que las clases de objetos se pueden usar como nuevos tipos, por
lo tanto se pueden usar en la composici´on de otros tipos
1 class B {
2 private:
3 int k;
4 double z;
5 public:
6 A a;
7 void g();
8 };
En este caso B::a es p´ublico, de forma que los m´etodos p´ublicos de A tambi´en
se pueden llamar sobre este campo, es decir
1 B b;
2 b.a.f(); // OK
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 282
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Composici´on y la cadena de inicializaci´on
Hemos visto que en el constructor de la clase podemos inicializar sus
miembros en la cadena de inicializaci´on. En particular tambi´en se pueden
llamar constructores de los subobjetos que forman parte de la clase
1 class B {
2 private:
3 int k;
4 double z;
5 public:
6 B() : a(234,"jaja") { }
7 A a;
8 void g();
9 };
En la cadena de inicializaci´on se pueden poner tanto constructores de
subobjetos como tambi´en inicializar objetos built-in (int, double...) por copia.
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 283
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Herencia
Otra forma de elaborar clases m´as complejas a partir de otras m´as simples es
por herencia.
1 class C : public A {
2 int k;
3 double z;
4 public:
5 void g();
6 };
Se dice que C es una clase derivada de A y A es la clase base de C.
Los m´etodos de A se pueden llamar ahora tambi´en sobre C. en este caso
estamos diciendo C es como A pero tiene algunas cosas adicionales. Al hacer
composici´on estamos diciendo que C contiene a un objeto de tipo A.
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 284
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Herencia (cont.)
Notar que en el caso de composici´on los miembros de A se acceden a trav´es
de B::a, es decir por ejemplo
1 B b;
2 b.a.c = ’5’;
mientras que en el caso de herencia, no existe directamente el miembro B::a
de manera que los miembros de A pasan a ser directamente miembros de C
1 C c;
2 c.c = ’7’;
Al declarar en la herencia que A es p´ublico, todos los miembros y m´etodos de
A ser´an vistos a trav´es de C con la privacidad que ten´ıan en A, es decir C.c es
p´ublico y C.i es privado. Por el contrario, si declaramos
1 class C : private A { . . .
entonces todos los campos de A son privados.
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 285
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Herencia (cont.)
Notar que con composici´on se pueden incluir en la nueva clase muchos
objetos del mismo tipo o de diferente tipo, mientras que con herencia no es
usual derivar de varias clases al mismo tiempo.
1 class A { . . . . };
2 class X { . . . . };
3
4 class B {
5 A a1,a2;
6 X x;
7 // . . .
8 };
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 286
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Redefinici´on de m´etodos
¿Qu´e pasa si la clase derivada tiene un m´etodo con el mismo nombre que la
clase base? Con composici´on no hay problema
1 class A {
2 public:
3 void f();
4 };
5
6 class B {
7 public:
8 A a;
9 void f();
10 };
11
12 B b;
13 b.f(); // llama la f de B
14 b.a.f(); // llama la f de A
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 287
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Redefinici´on de m´etodos (cont.)
Con herencia el nuevo m´etodo redefine u oculta el m´etodo anterior
1 class A {
2 public:
3 void f();
4 };
5
6 class B : public A {
7 public:
8 void f();
9 };
10
11 B b;
12 b.f(); // llama la f de B
13 b.A::f(); // llama la f de A
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 288
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Herencia protegida
Hay una forma de herencia que es intermedia entre p´ublico y privado, y es la
herencia protected. En este caso lo m´etodos de la clase son privados para el
exterior pero pueden ser usados como p´ublicos por la base derivada.
1 class Base {
2 int i;
3 protected:
4 int read() const { return i; }
5 void set(int ii) { i = ii; }
6 public:
7 Base(int ii = 0) : i(ii) {}
8 int value(int m) const { return m*i; }
9 };
10
11 class Derived : public Base {
12 int j;
13 public:
14 Derived(int jj = 0) : j(jj) {}
15 void change(int x) { set(x); }
16 };
17
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 289
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
18 int main() {
19 Derived d;
20 d.change(10);
21 }
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 290
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Upcasting
El compilador nos deja sin problema castear un puntero de la clase derivada a
la clase base, porque sabe que la clase derivada tiene todas las cosas de la
base
1 class Base { //. . .
2
3 class Derived : public Base { . . .
4
5 Derived d1, d2;
6 Base &b = d1;
7 Base *p = &d2;
Esto se llama upcasting. Sin embargo, si llamamos a un m´etodo de la clase
que est´a implementado en las dos, llama al de la base.
1 p->f(); // llama a Base::f()
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 291
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Polimorfismo
Nosotros queremos definir clases base que son gen´ericas (por ejemplo
Matrix) y plantear algoritmos/operaciones gen´ericos para las mismas (por
ejemplo GradConj()). Estos algoritmos toman un puntero a la clase base y
llaman operaciones gen´ericas sobre la misma (por ejemplo el producto matriz
vector MatVec()). Luego podemos definir clases derivadas para las matrices
de distinto tipo (llena, banda, sparse, sim´etrica...) La idea es que cuando el
algoritmo gen´erico GradConj() llama al m´etodo MatVec()), ´esta llamada sea
despachada a la funci´on correspondiente en la clase derivada.
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 292
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Polimorfismo (cont.)
Para que la llamada al m´etodo sea despachada a la clase derivada debemos
declarar al m´etodo virtual en la clase base.
1 class Base {
2 public:
3 virtual void f();
4 //. . .
5
6 class Derived : public Base {
7 public:
8 void f();
9 //. . .
10 }
11
12 Derived d1, d2;
13 Base &b = d1;
14 b.f(); // llama a Derived::f()
15
16 Base *p = d2;
17 p->f(); // llama a Derived::f()
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 293
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Ejemplo polimorfismo. Integral 1D/2D/3D
Queremos calcular la integral de funciones en segmentos ([a, b]) en 1D y
productos cartesianos ([xa, xb] × [ya, yb]) en 2D y 3D.
I1 =
xb
xa
f(x) dx,
I2 =
yb
ya
xb
xa
f(x, y) dx dy,
I3 =
zb
za
yb
ya
xb
xa
f(x, y, z) dx dy dz,
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 294
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Ejemplo polimorfismo. Integral 1D/2D/3D (cont.)
Empecemos definiendo el tipo de funciones de una variable
1 class scalarfun1d-t {
2 public:
3 virtual double eval(double x)=0;
4 };
Notemos que el m´etodo eval() est´a declarado =0 eso quiere decir que no se
implementar´a, por lo tanto es una clase virtual pura es decir que no se
pueden definir instancias de esta clase. S´olo es un prototipo del cual
podremos derivar clases concretas que podr´an ser integradas.
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 295
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Ejemplo polimorfismo. Integral 1D/2D/3D (cont.)
1 // LIBRARY CODE
2 class scalarfun1d-t {
3 public:
4 virtual double eval(double x)=0;
5 };
6
7 class integral1d-t {
8 public:
9 void set(int N, double a,double b,scalarfun1d-t *fxp);
10 double integral();
11 };
12
13 // USER CODE
14 class sin-fun-t : public scalarfun1d-t {
15 public:
16 double eval(double x) { return sin(x); }
17 } sin-fun;
18
19 int main() {
20 integral1d-t int1d;
21 int1d.set(100,0,1,&sin-fun);
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 296
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
22 cout << "Integral of sin(x) in [0,1] is "
23 << int1d.integral() << endl;
24 return 0
25 }
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 297
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Clase que calcula integral 1D
1 class integral1d-t {
2 private:
3 int N; // Nbr of integration pts
4 double xa,xb; // integration interval
5 scalarfun1d-t *fp; // ptr to function
6 public:
7 // Ctor, set values
8 integral1d-t(int Na=0,double xaa=NAN,
9 double xba=NAN,scalarfun1d-t *fpa=NULL) {
10 set(Na,xaa,xba,fpa);
11 }
12 // Set values
13 void set(int Na,double xaa,double xba,scalarfun1d-t *fpa) {
14 N=Na; xa=xaa; xb=xba; fp=fpa;
15 }
16 // Computes the integral using Simpson’s rule
17 double integral() {
18 double
19 h = (xb-xa)/N,
20 h2 = h/2.0,
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 298
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
21 finteg=0.0;
22 for (int j=0; j<N; j++) {
23 double x = j*h;
24 double f = fp->eval(x);
25 finteg += 2.0*f;
26 finteg += 4.0*fp->eval(x+h2);
27 }
28 finteg -= fp->eval(xa);
29 finteg += fp->eval(xb);
30 finteg *= h/6.0;
31 return finteg;
32 }
33 };
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 299
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Integral 2D. Versi´on cruda
La integral doble la hacemos como composici´on de dos integrales simples
I2 =
yb
ya
xb
xa
f(x, y) dx dy,
=
yb
ya
g(y) dy,
g(y) =
xb
xa
fy(x) dx.
fx(y) ≡ f(x, y).
x
y
xa xb
ya
yb
y
g(y)
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 300
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Integral 2D. Versi´on cruda (cont.)
1 class fy-t : public scalarfun1d-t {
2 public:
3 scalarfun2d-t *f2dp; // Ptr to 2var funct fx,y)
4 double y;
5 double eval(double x) { return f2dp->eval(x,y); }
6 } fy;
7
8 class g-t : public scalarfun1d-t {
9 public:
10 integral1d-t int1dx; // integral over x
11 double eval(double y) { // wrapper pass to calling class
12 fy.y = y;
13 return int1dx.integral();
14 }
15 } g;
16
17 class integral2d-t {
18 private:
19 int N; // Nbr of integr segments
20 double xa,xb,ya,yb; // rectangle corners
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 301
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
21 integral1d-t int1dy; // integral over y
22 public:
23 void set(int Na=0,double xaa=NAN,double xba=NAN,
24 double yaa=NAN,double yba=NAN,
25 scalarfun2d-t *f2dpa=NULL) {
26 N = Na; xa=xaa; xb=xba; ya=yaa; yb=yba;
27 fy.f2dp = f2dpa;
28 int1dy.set(N,ya,yb,&g);
29 g.int1dx.set(N,xa,xb,&fy);
30 }
31 integral2d-t(int Na=0, // Ctor
32 double xaa=NAN,double xba=NAN,
33 double yaa=NAN,double yba=NAN,
34 scalarfun2d-t *f2dpa=NULL) {
35 set(Na,xaa,xba,yaa,yba,f2dpa);
36 }
37 double integral() {
38 // 2D integral. Integrates over y the
39 // integral over x
40 return int1dy.integral();
41 }
42 };
43
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 302
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
44 // User code starts here----
45 // Specific 2var function to be integrated
46 class fun-t : public scalarfun2d-t {
47 public:
48 double eval(double x,double y) {
49 // Must give (2/pi)ˆ2 = 0.40528
50 return sin(0.5*M-PI*x)*sin(0.5*M-PI*y);
51 }
52 } fun;
53
54 int main() {
55 int N=10;
56
57 // 2D integration example
58 integral2d-t int2d(N,0.0,1.0,0.0,1.0,&fun);
59 cout << "integral(x,y) = " << int2d.integral() << endl;
60
61 return 0;
62 }
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 303
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Integral 2D. Versi´on cruda (cont.)
• fy y g son wrappers.
• fy toma una scalarfun2d_t y devuelve una scalarfun1d_t fijando y a un
valor (almacenado en el wrapper).
• g es una scalarfun1d_t. Usa un objeto de la clase integradora 1D llamado
int1dx. La funci´on eval correspondiente consiste en fijar el valor de y para
la fy y llamar a la clase integradora sobre y.
• Ambos objetos pertenecen a clases fy_t y g_t.
• En esta implementaci´on hemos hecho estas clases globales y totalmente
p´ublicas para simplificar.
• La clase integradora 2D utiliza otr integrador 1D (int1dy) para integrar
sobre y.
• Las dos instancias de integral1d_t son utilizadas en forma recursiva,
int1dy.eval() utiliza internamente a int1dx.eval() al evaluar la funci´on g().
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 304
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Integral 2D. Versi´on cruda (cont.)
1 #include <cmath>
2 #include <iostream>
3 #include <vector>
4 using namespace std;
5
6 // One variable function ’f(x)’
7 class scalarfun1d-t {
8 public:
9 virtual double eval(double x)=0;
10 };
11
12
13 // Two variables function ’f(x,y)’
14 class scalarfun2d-t {
15 public:
16 virtual double eval(double x,double y)=0;
17 };
18
19 // Two variables function ’f(x,y,z)’
20 class scalarfun3d-t {
21 public:
22 virtual double eval(double x,double y,double z)=0;
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 305
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
23 };
24
25 // Integral of a one var funct over an interval
26 class integral1d-t {
27 private:
28 int N; // Nbr of integration pts
29 double xa,xb; // integration interval
30 scalarfun1d-t *fp; // ptr to function
31 public:
32 // Ctor, set values
33 integral1d-t(int Na=0,double xaa=NAN,
34 double xba=NAN,scalarfun1d-t *fpa=NULL) {
35 set(Na,xaa,xba,fpa);
36 }
37 // Set values
38 void set(int Na,double xaa,double xba,scalarfun1d-t *fpa) {
39 N=Na; xa=xaa; xb=xba; fp=fpa;
40 }
41 // Computes the integral using Simpson’s rule
42 double integral() {
43 double
44 h = (xb-xa)/N,
45 h2 = h/2.0,
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 306
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
46 finteg=0.0;
47 for (int j=0; j<N; j++) {
48 double x = j*h;
49 double f = fp->eval(x);
50 finteg += 2.0*f;
51 finteg += 4.0*fp->eval(x+h2);
52 }
53 finteg -= fp->eval(xa);
54 finteg += fp->eval(xb);
55 finteg *= h/6.0;
56 return finteg;
57 }
58 };
59
60
61 // Integral of 2var functions over a rectangle
62 class integral2d-t {
63 private:
64 scalarfun2d-t *f2dp; // Ptr to 2var funct
65 integral1d-t int1dy, int1dx; // integrals over x and y
66 // For a given y gives the function fy(x) = f(x,y)
67 class fy-t : public scalarfun1d-t {
68 double y;
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 307
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
69 integral2d-t *i2dp; // ptr to calling class
70 friend class integral2d-t;
71 public:
72 double eval(double x) { return i2dp->f2dp->eval(x,y); }
73 } fy;
74 // For a given y, integral over x: g(y) = int-{x=xa}ˆxb f(x,y) dx
75 class g-t : public scalarfun1d-t {
76 integral2d-t *i2dp; // ptr to calling class
77 friend class integral2d-t;
78 public:
79 double eval(double y) { // wrapper pass to calling class
80 return i2dp->geval(y);
81 }
82 } g;
83 double geval(double y) {
84 // Integrates over x for y=cnst
85 fy.y = y;
86 return int1dx.integral();
87 }
88 int N; // Nbr of integr segments
89 double xa,xb,ya,yb; // rectangle corners
90 friend class fy-t;
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 308
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
91 friend class g-t;
92 public:
93 void set(int Na=0,double xaa=NAN,double xba=NAN,
94 double yaa=NAN,double yba=NAN,
95 scalarfun2d-t *f2dpa=NULL) {
96 N = Na; xa=xaa; xb=xba; ya=yaa; yb=yba;
97 f2dp = f2dpa;
98 int1dy.set(N,ya,yb,&g);
99 int1dx.set(N,xa,xb,&fy);
100 }
101 integral2d-t(int Na=0, // Ctor
102 double xaa=NAN,double xba=NAN,
103 double yaa=NAN,double yba=NAN,
104 scalarfun2d-t *f2dpa=NULL) {
105 set(Na,xaa,xba,yaa,yba,f2dpa);
106 g.i2dp = this;
107 fy.i2dp = this;
108 }
109 double integral() {
110 // 2D integral. Integrates over y the
111 // integral over x
112 return int1dy.integral();
113 }
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 309
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
114 };
115
116
117 // Integral of 3var functions over a cube
118 class integral3d-t {
119 private:
120 scalarfun3d-t *f3dp; // Ptr to 3var funct
121 integral2d-t int2dxy; // integral over x,y
122 integral1d-t int1dz; // integral over z
123 // For a given z gives the function fz(x,y) = f(x,y,z)
124 class fz-t : public scalarfun2d-t {
125 double z;
126 integral3d-t *i3dp; // ptr to calling class
127 friend class integral3d-t;
128 public:
129 double eval(double x,double y) {
130 return i3dp->f3dp->eval(x,y,z);
131 }
132 } fz;
133 // For a given z, gives g(z) = integral over x,y:
134 // g(z) = int-{x=xa}ˆxb int-{y=ya}ˆyb f(x,y,z) dx dy
135 class g-t : public scalarfun1d-t {
136 integral3d-t *i3dp; // ptr to calling class
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 310
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
137 friend class integral3d-t;
138 public:
139 double eval(double z) { // wrapper pass to calling class
140 return i3dp->geval(z);
141 }
142 } g;
143 double geval(double z) {
144 // Integrates over x,y for z=cnst
145 fz.z = z;
146 return int2dxy.integral();
147 }
148 int N; // Nbr of integr segments
149 double xa,xb,ya,yb,za,zb; // rectangle corners
150 friend class fz-t;
151 friend class g-t;
152 public:
153 void set(int Na,double xaa,double xba, // Set from args
154 double yaa,double yba,
155 double zaa,double zba,
156 scalarfun3d-t *f3dpa) {
157 N = Na; xa=xaa; xb=xba; ya=yaa; yb=yba; za=zaa; zb=zba;
158 f3dp = f3dpa;
159 int2dxy.set(N,xa,xb,ya,yb,&fz);
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 311
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
160 int1dz.set(N,za,zb,&g);
161 }
162 integral3d-t(int Na=0, // Ctor
163 double xaa=NAN,double xba=NAN,
164 double yaa=NAN,double yba=NAN,
165 double zaa=NAN,double zba=NAN,
166 scalarfun3d-t *f3dpa=NULL) {
167 set(Na,xaa,xba,yaa,yba,zaa,zba,f3dpa);
168 g.i3dp = this;
169 fz.i3dp = this;
170 }
171 double integral() { // Comp 3D integral. Integrates over z
172 return int1dz.integral();
173 }
174 };
175
176
177 // User code starts here----
178 // Specific 1var function to be integrated
179 class fun-t : public scalarfun1d-t {
180 public:
181 double eval(double x) {
182 // Must give (2/pi) = 0.63662
183 return sin(0.5*M-PI*x);
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 312
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
184 }
185 } fun;
186
187 // Specific 2var function to be integrated
188 class fun2-t : public scalarfun2d-t {
189 public:
190 double eval(double x,double y) {
191 // Must give (2/pi)ˆ2 = 0.40528
192 return sin(0.5*M-PI*x)*sin(0.5*M-PI*y);
193 }
194 } fun2;
195
196 // Specific 3var function to be integrated
197 class fun3-t : public scalarfun3d-t {
198 public:
199 double eval(double x,double y,double z) {
200 // Must give (2/pi)ˆ3 = 0.25801
201 return sin(0.5*M-PI*x)
202 *sin(0.5*M-PI*y)*sin(0.5*M-PI*z);
203 }
204 } fun3;
205
206 int main() {
207 int N=10;
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 313
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
208 // 1D integration example
209 integral1d-t int1d(N,0,1.0,&fun);
210 cout << "integral(x) = " << int1d.integral() << endl;
211
212 // 2D integration example
213 integral2d-t int2d(N,0.0,1.0,0.0,1.0,&fun2);
214 cout << "integral(x,y) = " << int2d.integral() << endl;
215
216 // 3D integration example
217 integral3d-t int3d(N,0.0,1.0,0.0,1.0,0.0,1.0,&fun3);
218 cout << "integral(x,y,z) = " << int3d.integral() << endl;
219
220 return 0;
221 }
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 314
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Integral 2D. Versi´on mejorada
Funciona pero tiene algunas desprolijidades, usa variables globales y las
clases auxiliares es mejor si se anidan en la clase que la utiliza integral2d_t.
1 class integral2d-t {
2 private:
3 scalarfun2d-t *f2dp; // Ptr to 2var funct
4 integral1d-t int1dy, int1dx; // integrals over x and y
5 // For a given y gives the function fy(x) = f(x,y)
6 class fy-t : public scalarfun1d-t {
7 double y;
8 integral2d-t *i2dp; // ptr to calling class
9 friend class integral2d-t;
10 public:
11 double eval(double x) { return i2dp->f2dp->eval(x,y); }
12 } fy;
13 // For a given y, integral over x: g(y) = int-{x=xa}ˆxb f(x,y) dx
14 class g-t : public scalarfun1d-t {
15 integral2d-t *i2dp; // ptr to calling class
16 friend class integral2d-t;
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 315
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
17 public:
18 double eval(double y) { // wrapper pass to calling class
19 return i2dp->geval(y);
20 }
21 } g;
22 double geval(double y) {
23 // Integrates over x for y=cnst
24 fy.y = y;
25 return int1dx.integral();
26 }
27 int N; // Nbr of integr segments
28 double xa,xb,ya,yb; // rectangle corners
29 friend class fy-t;
30 friend class g-t;
31 public:
32 void set(int Na=0,double xaa=NAN,double xba=NAN,
33 double yaa=NAN,double yba=NAN,
34 scalarfun2d-t *f2dpa=NULL) {
35 N = Na; xa=xaa; xb=xba; ya=yaa; yb=yba;
36 f2dp = f2dpa;
37 int1dy.set(N,ya,yb,&g);
38 int1dx.set(N,xa,xb,&fy);
39 }
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 316
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
40 integral2d-t(int Na=0, // Ctor
41 double xaa=NAN,double xba=NAN,
42 double yaa=NAN,double yba=NAN,
43 scalarfun2d-t *f2dpa=NULL) {
44 set(Na,xaa,xba,yaa,yba,f2dpa);
45 g.i2dp = this;
46 fy.i2dp = this;
47 }
48 double integral() {
49 // 2D integral. Integrates over y the
50 // integral over x
51 return int1dy.integral();
52 }
53 };
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 317
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Integral 3D
De la misma forma se puede hacer la integral en 3D combinando una integral
en 1D con otra en 2D.
1 class integral3d-t {
2 private:
3 scalarfun3d-t *f3dp; // Ptr to 3var funct
4 integral2d-t int2dxy; // integral over x,y
5 integral1d-t int1dz; // integral over z
6 // For a given z gives the function fz(x,y) = f(x,y,z)
7 class fz-t : public scalarfun2d-t {
8 double z;
9 integral3d-t *i3dp; // ptr to calling class
10 friend class integral3d-t;
11 public:
12 double eval(double x,double y) {
13 return i3dp->f3dp->eval(x,y,z);
14 }
15 } fz;
16 // For a given z, gives g(z) = integral over x,y:
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 318
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
17 // g(z) = int-{x=xa}ˆxb int-{y=ya}ˆyb f(x,y,z) dx dy
18 class g-t : public scalarfun1d-t {
19 integral3d-t *i3dp; // ptr to calling class
20 friend class integral3d-t;
21 public:
22 double eval(double z) { // wrapper pass to calling class
23 return i3dp->geval(z);
24 }
25 } g;
26 double geval(double z) {
27 // Integrates over x,y for z=cnst
28 fz.z = z;
29 return int2dxy.integral();
30 }
31 int N; // Nbr of integr segments
32 double xa,xb,ya,yb,za,zb; // rectangle corners
33 friend class fz-t;
34 friend class g-t;
35 public:
36 void set(int Na,double xaa,double xba, // Set from args
37 double yaa,double yba,
38 double zaa,double zba,
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 319
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
39 scalarfun3d-t *f3dpa) {
40 N = Na; xa=xaa; xb=xba; ya=yaa; yb=yba; za=zaa; zb=zba;
41 f3dp = f3dpa;
42 int2dxy.set(N,xa,xb,ya,yb,&fz);
43 int1dz.set(N,za,zb,&g);
44 }
45 integral3d-t(int Na=0, // Ctor
46 double xaa=NAN,double xba=NAN,
47 double yaa=NAN,double yba=NAN,
48 double zaa=NAN,double zba=NAN,
49 scalarfun3d-t *f3dpa=NULL) {
50 set(Na,xaa,xba,yaa,yba,zaa,zba,f3dpa);
51 g.i3dp = this;
52 fz.i3dp = this;
53 }
54 double integral() { // Comp 3D integral. Integrates over z
55 return int1dz.integral();
56 }
57 };
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 320
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Integral 1D/2D/3D. User code
1 class fun-t : public scalarfun1d-t {
2 public:
3 double eval(double x) {
4 // Must give (2/pi) = 0.63662
5 return sin(0.5*M-PI*x);
6 }
7 } fun;
8
9 // Specific 2var function to be integrated
10 class fun2-t : public scalarfun2d-t {
11 public:
12 double eval(double x,double y) {
13 // Must give (2/pi)ˆ2 = 0.40528
14 return sin(0.5*M-PI*x)*sin(0.5*M-PI*y);
15 }
16 } fun2;
17
18 // Specific 3var function to be integrated
19 class fun3-t : public scalarfun3d-t {
20 public:
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 321
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
21 double eval(double x,double y,double z) {
22 // Must give (2/pi)ˆ3 = 0.25801
23 return sin(0.5*M-PI*x)
24 *sin(0.5*M-PI*y)*sin(0.5*M-PI*z);
25 }
26 } fun3;
27
28 int main() {
29 int N=10;
30 // 1D integration example
31 integral1d-t int1d(N,0,1.0,&fun);
32 cout << "integral(x) = " << int1d.integral() << endl;
33
34 // 2D integration example
35 integral2d-t int2d(N,0.0,1.0,0.0,1.0,&fun2);
36 cout << "integral(x,y) = " << int2d.integral() << endl;
37
38 // 3D integration example
39 integral3d-t int3d(N,0.0,1.0,0.0,1.0,0.0,1.0,&fun3);
40 cout << "integral(x,y,z) = " << int3d.integral() << endl;
41
42 return 0;
43 }
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 322
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Polimorfismo: ej. suma de los elementos de un vector
Decargar vecsum.cpp
1 #include <cmath>
2 #include <iostream>
3 #include <vector>
4 using namespace std;
5
6 class vector-t {
7 public:
8 virtual int size()=0;
9 virtual double operator[ ](int j)=0;
10 };
11
12 double vecsum(vector-t &v) {
13 int N = v.size();
14 double sum = 0.0;
15 for (int j=0; j<N; j++) sum += v[j];
16 return sum;
17 }
18
19 // A stride, linearly spaced values
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 323
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
20 class stride-t : public vector-t {
21 private:
22 int N;
23 double start, inc;
24 public:
25 stride-t(int Na, double s,double i) :
26 N(Na), start(s), inc(i) { }
27 int size() { return N; }
28 double operator[ ](int j) { return start+j*inc; }
29 };
30
31 // A wrapper to a vector<double>
32 class vecwrap-t : public vector-t {
33 private:
34 const vector<double> *ap;
35 public:
36 vecwrap-t(const vector<double> &a) : ap(&a) { }
37 int size() { return ap->size(); }
38 double operator[ ](int j) { return (*ap)[j]; }
39 };
40
41 // A plain function that computes its values
42 class fun-t : public vector-t {
43 public:
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 324
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
44 int N;
45 double p;
46 fun-t() : N(10), p(3.0) { }
47 int size() { return N; }
48 double operator[ ](int j) { return pow(j,p); }
49 };
50
51 int main() {
52 stride-t stride(10,0,1);
53 cout << "sum(0. .9): " << vecsum(stride) << endl;
54
55 vector<double> a;
56 double p=3; int N=10;
57 a.resize(N);
58 for (int j=0; j<N; j++) a[j] = pow(j,p);
59 vecwrap-t vw(a);
60 cout << "sum-{j=0}ˆ{j=9} xˆ3 (with vecwrap): "
61 << vecsum(vw) << endl;
62
63 fun-t f;
64 cout << "sum-{j=0}ˆ{j=9} xˆ3 (with fun-t): "
65 << vecsum(f) << endl;
66
67 return 0;
68 }
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 325
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Contenedores de la
librer´ıa STL
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 326
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
La clase vector
• Inicialmente eran una serie de headers con clases desarrollado por
Hewlett Packard.
• Es una librer´ıa de contenedores (vectores, listas, conjuntos, maps...) y
algoritmos (ordenamiento, filtrado, operaciones de conjuntos, eliminar
elementos duplicados...)
• Est´an templatizados es decir cada contenedor puede obtener objetos de
un tipo arbitrario (todos del mismo), por ejemplo vector<int>,
vector<double>.
• Tambi´en puede contener objetos de clases definidas por el usuario
vector<A>, a condici´on de que la clase A cumpla con ciertas restricciones
(por ejemplo tener un constructor por defecto, operador de asignaci´on
a1=a2...)
• Muchos pueden anidarse, por ejemplo vector<vector<int>>.
• Algunos pueden involucrar m´as de un tipo, por ejemplo map<int,string>.
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 327
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
La clase vector
• Emula el comportamiento de un vector est´andar de C, pero se puede
redimensionar din´amicamente y libera sus recursos din´amicamente.
1 vector<int> v; // declara el vector
2 v.resize(N); // lo dimensiona a N elementos
3 // OJO preserva elementos existentes.
4 vector<int> v(N); // Lo crea con N elementos
5 int z; vector<int> v(N,z); // Lo crea con N elementos =z
6 v.clear(); // Elimina todos los elementos dejando al vector vac´ıo
• Tiene sobrecargado el operator[] para acceder para lectura/escritura los
elementos del vector. El acceso es en tiempo O(1).
1 x = v[j]; v[k]=z;
• v.push_back(z) inserta el elemento z al final (muy eficiente, O(1)
amortizado).
• z = v.front(), z = v.back() accede al primer y ´ultimo elemento del vector
(eficiente, O(1).
• Se puede acceder a los elementos a trav´es de iterators
1 // Comienzo del vector (v[0])
2 vector<int>::iterator q= v.begin();
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 328
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
3 int z = *q; // Se dereferencian como ptrs
4 q++; // Incrementa al siguiente elemento
*q equivale a v[0]. Despu´es de hacer el incremento equivale a v[1].
• La clase iterator es una clase anidada dentro de vector. Casi todos los
contenedores tienen su propia clase iterator.
• El iterator v.end() es un iterator pasado el ´ultimo elemento del vector
1 vector<int> v(10);
2 vector<int>::iterator q = v.end();
3 // ERROR: q is not dereferenciable
4 cout << "Last element is " << *q << endl;
q apunta a v[10] (el ´ultimo elemento es v[9]).
• Se puede iterar sobre todo el vector as´ı
1 // Suma todos los elementos de v
2 double sum = 0;
3 vector<int>::iterator q = v.begin();
4 while (q!=v.end()) {
5 sum += *q;
6 q++;
7 }
• Notar que q++ se puede hacer ya que el operator++ est´a sobrecargado para
la clase iterator. Igual que para enteros existe la versi´on prefija y postfija.
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 329
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
• Para vector tambi´en se puede iterar como con un vector com´un
1 double sum = 0;
2 for (int j=0; j<v.size(); j++) sum += v[j];
Pero esto se puede usar s´olo con vector, con iteradores se puede iterar
sobre casi cualquiera de los otros contenedores.
• Los iterators de vector<> soportan aritm´etica de punteros. Esto es s´olo
v´alido para los iterators de vector, no para list<> o map<> por ejemplo.
• Se puede insertar un elemento en cualquier posici´on del vector, sin
embargo esto puede ser costoso (O(n)).
1 vector<double> v(100,0);
2 q = v.begin() + 50; // Apunta al elemento v[50]
3 v.insert(q,33); // Inserta un 33 en la posici´on 50
Despu´es de esto el vector tiene 101 elementos. Por supuesto esto implica
no solo redimensionar el vector sino tambi´en copiar los elementos en
[50,99] a [51,100].
• Para pasar los vectores como argumentos conviene hacerlo a trav´es de
referencias para evitar la copia. Para indicar que la funci´on no modifica al
vector se debe declarar el argumento como const.
1 double vecsum(const vector<double> &w)
• Pero entonces se debe iterar sobre el mismo con un const_iterator
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 330
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
1 double vecsum(const vector<double> &w) {
2 double sum = 0.0;
3 vector<double>::const-iterator q = w.begin();
4 while (q!=w.end()) sum += *q++
5 return sum;
6 }
• Como es declarado un const_iterator no se le puede asignar un valor
1 vector<double>::const-iterator q;
2 //. . . .
3 *q = z; // error!
• Como muchos otros contenedores de las STL, permite hacer un swap con
otro contenedor
1 vector<double> v,w;
2 // Llena v y w . . .
3 v.swap(w);
Equivale a
1 vector<double> v,w, tmp;
2 // Llena v y w . . .
3 tmp = v;
4 v = w;
5 w = tmp;
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 331
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Pero sin hacer copias ni duplicados, o sea es muy eficiente.
• Tambi´en se puede borrar elementos o un rango de elementos
1 w.erase(q); // Elimina el elemento en q (ineficiente)
2 w.erase(p,q); // Elimina todo el rango [p,q) (ineficiente)
3 w.pop-back(); // Elimina el ultimo elemento (eficiente)
• En toda la documentaci´on (y en general en ciencias de la computaci´on) se
utilizan rangos cerrado/abierto [p,q) que quiere decir todos los elementos
desde p a q incluyendo a p pero sin incluir a q.
• vector<> como casi todos los otros contenedores soportan asignaci´on:
operator= (deep copy), operator==, (comparaci´on por igualdad y distinto).
• Para usarlo
1 #include <vector>
2 using namespace std;
• Como casi todos los otros contenedores tiene bool v.isempty() (retorna
verdadero si el contenedor est´a vac´ıo).
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 332
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Algoritmos in-place
• Cuando se escriben c´odigos que manipulan contenedores muy grandes
(en tama˜no de memoria requerida) es importante saber cuanta memoria
adicional se requiere para realizar la operaci´on.
• Si el contenedor es de longitud n y la cantidad de memoria requerida es
O(1) es decir no crece con el tama˜no del contenedor se dice que el
algoritmo es in-place.
• Por ejemplo si queremos intercambiar los contenidos de dos vectores x e
y podemos utilizar las siguientes opciones
1 // VERSION 1 (in-place)
2 for (int j=0; j<N; j++){
3 double aux=x[j];
4 x[j]=y[j];
5 y[j]=aux;
6 }
7
8 // VERSION 2 (NOT in-place)
9 vd-t aux=x;
10 x=y; y=aux;
11
12 // VERSION 3: Uses C++ vector<> builtin swap
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 333
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
13 x.swap(y);
14
15 // VERSION 4: Uses generic STL swap
16 #include <algorithm>
17 swap(x,y);
• La versi´on 1 es in-place, ya que si bien requiere de memoria adicional (el
int j y double aux), son 12 bytes y no crece con el tama˜no del vector N.
• En cambio para la versi´on 2, SI requiere de el vector aux que es de tama˜no
N, por lo tanto NO es in-place.
• La versi´on 3, utiliza el swap() builtin de la clase vector<> y SI es in-place de
acuerdo a lo que dice la documentaci´on. Da lo mismo hacer x.swap(y) o
y.swap(x).
• La versi´on 4 utiliza el algoritmo gen´erico de las STL que funciona para
casi cualquier contenedor pero que no est´a optimizado, por lo tanto
puede ser que en la pr´actica sea equivalente a la versi´on 1.
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 334
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
La clase list
• El contenedor lista (list<>) es (como vector<>) un contenedor lineal es
decir los elementos en la lista se pueden asociar con una posici´on entera.
Sin embargo no se puede acceder a la posici´on m de la lista en forma
eficiente (es decir O(1)) ya que los elementos est´an almacenados en
celdas enlazadas.
1 list<double> L;
2 // pone elementos en L. . .
3 double z = L[m]; // NO, [ ] s´olo para vectores
4 double z;
• S´olo se puede acceder al elemento m-´esimo haciendo un lazo.
1 double z;
2 list<double>::iterator q = L.begin();
3 for (int j=0; j<m; j++) q++;
4 z = *q; // Accede al elemento m
• La lista es doblemente enlazada es decir que se puede avanzar en las dos
direcciones (q++ y q--) eficientemente (O(1)).
• Existe otra clase slist<> que es simplemente enlazada, por lo tanto q++ es
O(1), mientras que q-- es O(n) (debe ir al principio y recorrer la lista
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 335
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
hasta encontrar la celda que apunta a q).
• El inter´es de list<> es que permite insertar en cualquier posici´on muy
eficientemente (O(1))
1 list<double> L;
2 // Pone elementos en L. . .
3 // q apunta a cualquier posici´on en L
4 q = L.insert(q,w); // Inserta un nuevo elemento en
5 // el medio de la lista
• insert retorna la posici´on “refrescada” q.
1 L.insert(q,w); // deja q invalido
2 z = *q; // posible error en tiempo de ejecuci´on
3
4 q = L.insert(q,w); // OK refrezca q
5 z = *q; // OK!
• Para borrar un elemento q = L.erase(q);, tambi´en se debe refrescar el
iterator.
1 list<int>::iterator q = L.begin();
2 while (q!=L.end()) q = L.erase(q);
Equivale a L.clear(), elimina todos los elementos de a uno por el frente.
• Tambi´en se puede pasar todo un rango de una lista a otra
1 list<int> L1,L2;
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 336
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
2 // Pone elementos en L1, y L2
3 L1.splice(r,L2,p,q));
inserta todo el rango [p,q) de L2 en la posici´on r de L1. MUY EFICIENTE
(O(1)).
• list<> tambi´en tiene swap. De hecho swap se puede implementar para list
en t´erminos de splice
1 list<int> L1,L2,tmp;
2 // Pone elementos en L1, y L2
3 tmp.splice(tmp.begin(),L1.begin(),L1.end());
4 L1.splice(L1.begin(),L2.begin(),L2.end());
5 L2.splice(L2.begin(),tmp.begin(),tmp.end());
Toda la operaci´on es O(1), por lo tanto es tan eficiente como swap. Pero
splice() es m´as general (es como swap pero para pedazos de lista).
• vector no tiene splice().
• Los headers son #include <list> y <slist>
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 337
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
La clase set
• Los conjuntos son contenedores que almacenan elementos diferentes
entre s´ı.
1 set<int> S;
2 for (int j=0; j<10; j++) S.insert(j);
3 S.insert(5); // No hace nada (5 ya estaba)
• El m´etodo find(x) retorna la posici´on donde se encuentra un elemento
dado x, si el elemento no est´a retorna S.end()
1 set<int>::iterator q = S.find(x);
2 if (q!=S.end()) {
3 // x est´a en S y *q==x
4 }
• find() es muy eficiente (O(log n)). Esta es la condici´on de dise˜no de set.
• Si se declara un set<A> entonces la clase A tiene que tener los requisitos
de antes (ctor por defecto, operador de asignaci´on). Pero adem´as debe
tener sobrecargado el operator<. Esto es as´ı ya que el find() es eficiente
porque guarda los elementos ordenados.
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 338
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
• Se puede recorrer los elementos con un iterador, est´an ordenados por
operator<
1 set<int>::iterator q = S.begin();
2 while (q!=S.end()) cout << *q++ << " ";
3 cout << endl;
Imprime todos los elementos ordenados por operator<
• El header correspondiente es <set>
• Notar que insert() no toma un iterator (como en list vector). En set no se
inserta en una posici´on en particular, ya que el mismo contenedor
mantiene los elementos en un cierto orden.
• Hay dos sabores de erase
1 S.erase(q); // Erase de un iterator (debe ser dereferenciable)
2 int z = S.erase(x); // erase de un elemento
El primero toma un iterator que debe ser dereferenciable, elimina el
elemento correspondiente y no retorna nada. El segundo toma un
elemento x y se fija si est´a o no en el conjunto. Si est´a lo elimina del
conjunto y si no, no hace nada. En ambos casos el valor de retorno es el
n´umero de elementos efectivamente eliminados, es decir 1 o 0.
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 339
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
• Operaciones binarias de conjuntos: C = A ∩ B
1 set-intersection(a.begin(),a.end(),b.begin(),b.end(),
2 inserter(c,c.begin()));
• Se pueden utilizar las funciones que realizan las operaciones binarias.
Est´an en el header <algorithm>. No son m´etodos de la clase, son
funciones friend.
• C = A ∪ B
1 C.clear();
2 set-union(A.begin(),A.end(),B.begin(),B.end(),
3 inserter(C,C.begin()));
• C = A − B
1 set-difference(a.begin(),a.end(),b.begin(),b.end(),
2 inserter(c,c.begin()));
• Notar que en principio opera sobre un rango en A y otro en B e inserta la
uni´on de los mismos (sin elementos duplicados) en C. De la forma en que
est´a llamada arriba hace la operaci´on est´andar de uni´on.
• C = A − B
1 C.clear();
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 340
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
2 set-difference(A.begin(),A.end(),B.begin(),B.end(),
3 inserter(C,C.begin()));
• C = A ∩ B
1 C.clear();
2 set-intersection(A.begin(),A.end(),B.begin(),B.end(),
3 inserter(C,C.begin()));
• Las operaciones binarias son muy eficientes O(n log n).
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 341
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
La clase map
• Representa una correspondencia entre claves de un conjunto dominio y
un conjunto imagen o contradominio. Como si fuera una base de datos
almacena pares (clave,valor) ordenados por la clave y despu´es se puede
buscar las asignaciones por la clave.
• Ejemplo, sueldos de los empleados
1 map<int,double> sueldos;
2 sueldos[13234567] = 23000.34;
3 sueldos[30245654] = 18356.34;
4 . . . .
5 int dni = 34567234;
6 if (sueldos.find(dni)==sueldos.end()) {
7 // Este empleado no tiene asignado un sueldo en la tabla. . .
8 } else {
9 cout << "el sueldo correspondiente es " << sueldos[dni] << endl;
10 }
• El nombre utilizado para los tipos es key_t para el dominio, range_t. En el
ejemplo anterior key_t es int y range_t es double.
• Cuando se itera sobre el map con el lazo t´ıpico
1 map<int,double>::iterator q = sueldos.begin();
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 342
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
2 while (q!=sueldos.end()) {
3 cout << "DNI " << q->first << ", sueldo " << q->second << endl;
4 q++;
5 }
• Notar que los iteradores iteran sobre los pares clave, valor, de hecho son
estruturas de tipo pair<int,double>.
• El contenedor pair es el m´as b´asico de las STL y permite agrupar dos
elementos de tipo diferente o igual: pair<int,int> dos ints,
pair<int,string>....
• Los campos de pair se acceden por los miembros first y second.
1 pair<int,double> p;
2 p.first = 23;
3 p.second = 234.56;
• Tambi´en se puede declarar pair<int,double> p(23,45.67);
• El map tiene un efecto colateral no com´un que es que si indexamos por
una clave que no tiene asignado un valor entonces crea una asginaci´on
poniendo como imagen el constructor por defecto de range_t
1 map<int,string> M;
2 string z = M[5]; // Asigna z= string vacio !!!
• El tipo key_t tiene los mismos requerimientos que para un set es decir:
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 343
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
constructor por defecto y por copia, operador de asignaci´on, operator<.
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 344
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Algoritmos
• Permiten operar sobre los diferentes contenedores. Muchas veces en
forma transparente, el mismo algoritmo se puede aplicar a diferentes
contenedores.
• Tal vez el m´as paradigm´atico y util es sort
1 vector<double> v;
2 // Pone elementos en v. . .
3 // Ordena por valor absoluto
4 sort(v.begin(),v.end());
sort(p,q) ordena los elementos en el rango [p,q). Notar que no se le pasa
el contenedor, solo dos iteradores.
• Si hay que ordenar todo el contenedor hay que pasar v.begin(), v.end()
• Se puede utilizar tambi´en para listas
• Para conjuntos no tiene sentido, ya est´an internamente ordenados.
• Para clases (vector<A>) ordena por operator< por lo tanto debe estar
sobrecargado.
• Si se quiere ordenar por otro criterio y no se puede modificar el operator<
se puede pasar una funci´on de comparaci´on:
1 // Funcion de comparacion por valor absoluto
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 345
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
2 bool comp(int x,int y) { return abs(x)<abs(y); }
3 vector<int> v;
4 // Pone elementos en v. . .
5 sort(v.begin(),v.end(),comp);
• Es MUY r´apido, O(n log n).
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 346
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Programaci´on funcional
• Podemos escribir algoritmos que modifican los valores de un vector (u
otro contenedor), por ejemplo sumarle a todos los valores contenidos en
un ´arbol un valor, o duplicarlos.
1 void vecsum(vector<int> &v,int w) {
2 for (int j=0; j<w.size(); j++) v[j] += w;
3 }
4
5 void vecscale(vector<int> &v,int w) {
6 for (int j=0; j<w.size(); j++) v[j] *= w;
7 }
• Todos estos son casos particulares de un algoritmo m´as general
apply(v,f) que tiene como argumentos un vector v y una “funci´on
escalar” T f(T) (donde T es el tipo del vector). y le aplica a cada uno de
los valores nodales la funci´on en cuesti´on. Este es un ejemplo de
“programaci´on funcional”, es decir, programaci´on en los cuales los datos
de los algoritmos pueden ser tambi´en funciones.
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 347
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Programaci´on funcional (cont.)
• C++ tiene soporte para la programaci´on funcional pasando “punteros a
funciones”. Tambi´en se puede usar “functors”, clases que sobrecargan el
operador ().
• Lenguajes funcionales puros: Lisp/Scheme, ML, Haskell... las funciones
son “objetos de primera clase”.
• Soluci´on funcional:
1 void apply(vector<int>&v,int (*f)(int)) {
2 int N = v.size();
3 for (int j=0; j<N; j++) v[j] = f(v[j]);
4 }
5
6 int sum10(int x) { return x+10; }
7
8 int scale10(int x) { return x*10; }
9
10 int main() {
11 int N=10;
12 vector<int> v(N);
13 for (int j=0; j<N; j++) v[j] = j;
14 dump(v,"v antes");
15 apply(v,sum10);
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 348
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
16 dump(v,"v += 10");
17 apply(v,scale10);
18 dump(v,"v *= 10");
19 return 0;
20 }
Da lo siguiente:
1 [mstorti@galileo sources]$$ ./functional.bin
2 v antes: 0 1 2 3 4 5 6 7 8 9
3 v += 10: 10 11 12 13 14 15 16 17 18 19
4 v *= 10: 100 110 120 130 140 150 160 170 180 190
5 [mstorti@galileo sources]$$
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 349
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Programaci´on funcional (cont.)
• Se pasa el puntero a la funci´on.
• La “signatura” es int f(int). La declaraci´on de punteros a tales
funciones se hace reemplazando en la signatura el nombre de la funci´on
por (*) es decir int (*)(int).
• Dentro de esta funci´on auxiliar el puntero a funci´on f se aplica como una
funci´on normal.
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 350
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Programaci´on funcional (cont.)
Soluci´on funcional con clases y polimorfismo
1 class map-t {
2 public:
3 virtual int f(int)=0;
4 };
5
6 void apply(vector<int>&v,map-t &m) {
7 int N = v.size();
8 for (int j=0; j<N; j++) v[j] = m.f(v[j]);
9 }
10
11 class sum-t : public map-t {
12 public:
13 int w;
14 int f(int x) { return x+w; }
15 } sum;
16
17 class scale-t : public map-t {
18 public:
19 int w;
20 int f(int x) { return x*w; }
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 351
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
21 } scale;
22
23 int main() {
24 int N=10;
25 vector<int> v(N);
26 for (int j=0; j<N; j++) v[j] = j;
27 dump(v,"v antes");
28 sum.w = 10;
29 apply(v,sum);
30 dump(v,"v += 10");
31
32 sum.w = 30;
33 apply(v,sum);
34 dump(v,"v += 30");
35
36 scale.w = 10;
37 apply(v,scale);
38 dump(v,"v *= 10");
39
40 scale.w = 2;
41 apply(v,scale);
42 dump(v,"v *= 2");
43
44 return 0;
45 }
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 352
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Da lo siguiente:
1 [mstorti@galileo sources]$ ./functional2.bin
2 v antes: 0 1 2 3 4 5 6 7 8 9
3 v += 10: 10 11 12 13 14 15 16 17 18 19
4 v += 30: 40 41 42 43 44 45 46 47 48 49
5 v *= 10: 400 410 420 430 440 450 460 470 480 490
6 v *= 2: 800 820 840 860 880 900 920 940 960 980
7 [mstorti@galileo sources]$
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 353
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Otro ejemplo de progr. fun. Reducci´on
• reduce(v,g,null) que toma como argumentos un vector v y una funci´on
asociativa int g(int,int) (por ejemplo la suma, el producto, el m´aximo o
el m´ınimo) y devuelve el resultado de aplicar la funci´on asociativa a todos
los valores nodales, hasta llegar a un ´unico valor.
• null es el valor nulo para esa funci´on asociativa, es decir g(x,null)=x para
cualquier x.
Para g=+ es null=0, ya que es siempre x+0=0
Para g=* es null=1, ya que es siempre x*1=x
Para g=max es null=-Inf, ya que es siempre max(x,-Inf)=x
Para g=min es null=+Inf, ya que es siempre min(x,+Inf)=x
Para g=|| es null=false, ya que es siempre x||false=x
Para g=&& es null=true, ya que es siempre x||true=x
1 void filter-odd(vector<int> &v) {
2 vector<int> tmp;
3 int N=v.size();
4 for (int j=0; j<N; j++)
5 if (v[j]%2==0) tmp.push-back(v[j]);
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 354
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
6 v = tmp;
7 }
8
9 typedef bool (*pred-t)(int);
10
11 void filter(vector<int> &v,pred-t p) {
12 vector<int> tmp;
13 int N=v.size();
14 for (int j=0; j<N; j++) if (p(v[j])) tmp.push-back(v[j]);
15 v = tmp;
16 }
17
18 bool even(int x) { return x%2==0; }
19
20 bool positive(int x) { return x>0; }
21
22 int main() {
23 int N=10;
24 vector<int> v(N),vcpy;
25 for (int j=0; j<N; j++) v[j] = j;
26 vcpy = v;
27
28 dump(v,"v antes");
29 filter-odd(v);
30 dump(v,"even(v)");
31
32 v.resize(N);
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 355
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
33 for (int j=0; j<N; j++) v[j] = j-N/2;
34
35 dump(v,"v antes");
36 filter(v,positive);
37 dump(v,"positive(v) ");
38
39 return 0;
40 }
Da:
1 [mstorti@galileo sources]$ ./reduce.bin
2 v antes: 0 1 2 3 4 5 6 7 8 9
3 sum(v): 45
4 max(v): 9
5 min(v): 0
6 [mstorti@galileo sources]$
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 356
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Prog funcional. Filtros
• Otra aplicaci´on pueden ser “filtros”, como la funci´on filter_odd, elimina
los elementos impares.
• Podr´ıamos escribir una funci´on remove_if(v,pred) que tiene como
argumentos un vector v y una funci´on predicado bool pred(T). La funci´on
remove_if elimina todos los elementos x para cuyos valores la funci´on
pred(*n) retorna verdadero. La funci´on filter_odd se podr´ıa obtener
entonces simplemente pasando a remove_if una funci´on predicado que
retorna verdadero si el argumento es impar.
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 357
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Versi´on funcional
1 void filter-odd(vector<int> &v) {
2 vector<int> tmp;
3 int N=v.size();
4 for (int j=0; j<N; j++)
5 if (v[j]%2==0) tmp.push-back(v[j]);
6 v = tmp;
7 }
8
9 typedef bool (*pred-t)(int);
10
11 void filter(vector<int> &v,pred-t p) {
12 vector<int> tmp;
13 int N=v.size();
14 for (int j=0; j<N; j++) if (p(v[j])) tmp.push-back(v[j]);
15 v = tmp;
16 }
17
18 bool even(int x) { return x%2==0; }
19
20 bool positive(int x) { return x>0; }
21
22 int main() {
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 358
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
23 int N=10;
24 vector<int> v(N),vcpy;
25 for (int j=0; j<N; j++) v[j] = j;
26 vcpy = v;
27
28 dump(v,"v antes");
29 filter-odd(v);
30 dump(v,"even(v)");
31
32 v.resize(N);
33 for (int j=0; j<N; j++) v[j] = j-N/2;
34
35 dump(v,"v antes");
36 filter(v,positive);
37 dump(v,"positive(v) ");
38
39 return 0;
40 }
Da:
1 [mstorti@galileo sources]$ ./filter.bin
2 v antes: 0 1 2 3 4 5 6 7 8 9
3 even(v): 0 2 4 6 8
4 v antes: -5 -4 -3 -2 -1 0 1 2 3 4
5 positive(v) : 1 2 3 4
6 [mstorti@galileo sources]$
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 359
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
Versi´on funcional con clases
1 class pred-t {
2 public:
3 virtual bool f(int)=0;
4 };
5
6 void remove-if(vector<int>&v,pred-t &p) {
7 vector<int> tmp;
8 int N = v.size();
9 for (int j=0; j<N; j++) if(p.f(v[j])) tmp.push-back(v[j]);
10 v = tmp;
11 }
12
13 class even-t : public pred-t {
14 public:
15 bool f(int x) { return x%2==0; }
16 } even;
17
18 class positive-t : public pred-t {
19 public:
20 bool f(int x) { return x>0; }
21 } positive;
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 360
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))
Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz
22
23 int main() {
24 int N=10;
25 vector<int> v(N),vcpy;
26 for (int j=0; j<N; j++) v[j] = j-N/2;
27 vcpy = v;
28
29 dump(v,"v antes");
30 remove-if(v,even);
31 dump(v,"even(v)");
32
33 v = vcpy;
34 dump(v,"v antes");
35 remove-if(v,positive);
36 dump(v,"positive(v) ");
37
38 return 0;
39 }
Da:
1 [mstorti@galileo sources]$ ./filter2.bin
2 v antes: -5 -4 -3 -2 -1 0 1 2 3 4
3 even(v): -4 -2 0 2 4
4 v antes: -5 -4 -3 -2 -1 0 1 2 3 4
5 positive(v) : 1 2 3 4
6 [mstorti@galileo sources]$
Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 361
((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300)
(processed-date Wed May 27 12:45:10 2015 -0300))

Más contenido relacionado

PDF
SIMBOLOGIA ELECTRICIDAD 3º ESO
PPTX
Semiconductores
PDF
Simbolos cajas registros canalizaciones
PPTX
Unidades de las Bobinas en el campo Automotriz
PDF
Canalizacion unistrut
PDF
Simbologia
PDF
Rapport du CIGRE : Innovative solutions for overhead lines supports version-i...
 
PDF
Simbolos graficos-en-electricidad
SIMBOLOGIA ELECTRICIDAD 3º ESO
Semiconductores
Simbolos cajas registros canalizaciones
Unidades de las Bobinas en el campo Automotriz
Canalizacion unistrut
Simbologia
Rapport du CIGRE : Innovative solutions for overhead lines supports version-i...
 
Simbolos graficos-en-electricidad

La actualidad más candente (20)

PDF
Tecnolite Home Cat 22-23-1.pdf
DOCX
Tabla tuberia cable
PPT
Proyecto termoelectrica
PDF
Cálculo de Deman Máxima.-Act.N°4.pdf
PDF
15.2 reti idrauliche-ii
PPTX
Funcionamiento de-los-transformadores
PDF
Código_Nacional_de_Electricidad__Utilización_ (1).pdf
PDF
PDF
Monitoreo Integral de Transformadores.pdf
DOCX
Práctica - Convertir fuente ATX a fuente de laboratorio
PDF
Diseño de subestaciones
PDF
Enchufes y Tomacorrientes NEMA
PPTX
Plano electrico
PDF
Interruptores potencia at siemens
PPTX
Informe de acumuladores
PPTX
Presentacion power point jonathan sanchez
PDF
Simbología de la instalación eléctri ca
PDF
67496524 libro-instalaciones-electric-as-umss
PPTX
Diapositivas interruptor termomagnetico
PDF
Simbolos lineas transmision distribucion
Tecnolite Home Cat 22-23-1.pdf
Tabla tuberia cable
Proyecto termoelectrica
Cálculo de Deman Máxima.-Act.N°4.pdf
15.2 reti idrauliche-ii
Funcionamiento de-los-transformadores
Código_Nacional_de_Electricidad__Utilización_ (1).pdf
Monitoreo Integral de Transformadores.pdf
Práctica - Convertir fuente ATX a fuente de laboratorio
Diseño de subestaciones
Enchufes y Tomacorrientes NEMA
Plano electrico
Interruptores potencia at siemens
Informe de acumuladores
Presentacion power point jonathan sanchez
Simbología de la instalación eléctri ca
67496524 libro-instalaciones-electric-as-umss
Diapositivas interruptor termomagnetico
Simbolos lineas transmision distribucion
Publicidad

Destacado (20)

PDF
Build your own electronics lab
PDF
Week 13 vibration measurements
PPTX
Damped Oscillations
PPTX
Vibration Energy Harvesting - Between theory and reality
PPT
Vibration and frequency measuring instruments
PDF
The fundemental of electronics ebook
ODP
4.2 damped harmonic motion
PPT
Topic 3 forced oscillator
PPTX
Vibration measuring instrument - Vibrometer
PPT
6.2 Damped and forced oscillations
PPTX
Tuned mass damper
PDF
Air pulse fruit harvester
PPSX
Merchant's circle
PPT
Vibration and damping
PDF
Theory of-metal-cutting
PPT
Mechanics of metal cutting
PPT
Speed,velocity,acceleration
PPT
Speed, Velocity And Acceleration
PPT
Mechanical Vibrations all slides
Build your own electronics lab
Week 13 vibration measurements
Damped Oscillations
Vibration Energy Harvesting - Between theory and reality
Vibration and frequency measuring instruments
The fundemental of electronics ebook
4.2 damped harmonic motion
Topic 3 forced oscillator
Vibration measuring instrument - Vibrometer
6.2 Damped and forced oscillations
Tuned mass damper
Air pulse fruit harvester
Merchant's circle
Vibration and damping
Theory of-metal-cutting
Mechanics of metal cutting
Speed,velocity,acceleration
Speed, Velocity And Acceleration
Mechanical Vibrations all slides
Publicidad

Similar a Programacion en C++ para Ciencia e Ingeniería (20)

ODP
Software Libre como pilar en el Grid Computing
PPTX
Ingeniando el software en tiempos de crisis
PDF
Introducción Análisis y Diseño
PDF
Aterrizando la Inteligencia Artificial
PDF
2015 16 09 arq requisitos para presentar proyecto
PPT
Mda Para Dummies
PDF
6. dibujo industrial avanzado
PPTX
IMPLEMENTCIÓN DE SOFTWARE DE MATRÍCULA "ISM" (PMBOK)
PPTX
PDF
Rackio framework
PDF
Introducci n al_dise_o_en_ing._mec_nica
DOCX
Practica 2
PDF
Arquitectura de computadoras ii
PPTX
Sesión 2: Ejemplos y prácticas en Python
DOCX
Practica 2 problemas de programacion
PDF
Aprendizaje Estadístico con Python - 4to Encuentro Software libre 2013
PDF
C++ Como Programar - Deitel 6edi.pdf
PDF
Concepto Básicos Algoritmia
PPT
Complementación de la exposición sobre “seminario”
Software Libre como pilar en el Grid Computing
Ingeniando el software en tiempos de crisis
Introducción Análisis y Diseño
Aterrizando la Inteligencia Artificial
2015 16 09 arq requisitos para presentar proyecto
Mda Para Dummies
6. dibujo industrial avanzado
IMPLEMENTCIÓN DE SOFTWARE DE MATRÍCULA "ISM" (PMBOK)
Rackio framework
Introducci n al_dise_o_en_ing._mec_nica
Practica 2
Arquitectura de computadoras ii
Sesión 2: Ejemplos y prácticas en Python
Practica 2 problemas de programacion
Aprendizaje Estadístico con Python - 4to Encuentro Software libre 2013
C++ Como Programar - Deitel 6edi.pdf
Concepto Básicos Algoritmia
Complementación de la exposición sobre “seminario”

Más de Storti Mario (12)

PDF
Avances en la modelización computacional de problemas de interacción Fluido-E...
PDF
Advances in the Solution of NS Eqs. in GPGPU Hardware. Second order scheme an...
PDF
Advances in the Solution of Navier-Stokes Eqs. in GPGPU Hardware. Modelling F...
PDF
Automatic high order absorption layers for advective-diffusive systems of equ...
PDF
El Método Científico
PDF
Gpuslides
PDF
Supercomputadoras en carrera
PDF
Cosechadora Innovar
PDF
HPC course on MPI, PETSC, and OpenMP
PDF
Dynamic Absorbing Boundary Conditions
PDF
Actividades de Transferencia en CIMEC
PDF
Algoritmos y Estructuras de Datos
Avances en la modelización computacional de problemas de interacción Fluido-E...
Advances in the Solution of NS Eqs. in GPGPU Hardware. Second order scheme an...
Advances in the Solution of Navier-Stokes Eqs. in GPGPU Hardware. Modelling F...
Automatic high order absorption layers for advective-diffusive systems of equ...
El Método Científico
Gpuslides
Supercomputadoras en carrera
Cosechadora Innovar
HPC course on MPI, PETSC, and OpenMP
Dynamic Absorbing Boundary Conditions
Actividades de Transferencia en CIMEC
Algoritmos y Estructuras de Datos

Último (10)

PPTX
Tratará sobre Grafos_y_Arboles_Presentacion.pptx
PPTX
Conceptos basicos de Base de Datos y sus propiedades
PDF
Su punto de partida en la IA: Microsoft 365 Copilot Chat
PPTX
Fundamentos de Python - Curso de Python dia 1
PPTX
Implementación equipo monitor12.08.25.pptx
PDF
AutoCAD Herramientas para el futuro, Juan Fandiño
DOCX
trabajo programacion.docxxdxxxddxdxxdxdxxxdxxdxdxd
PDF
Clase 3 - Presentación visual (Insertando objetos visuales) POWER POINT.pdf
PPTX
ORIGEN DE LA IA - GRADO 1102 INTELIGENCIA
PPTX
sistemas de informacion.................
Tratará sobre Grafos_y_Arboles_Presentacion.pptx
Conceptos basicos de Base de Datos y sus propiedades
Su punto de partida en la IA: Microsoft 365 Copilot Chat
Fundamentos de Python - Curso de Python dia 1
Implementación equipo monitor12.08.25.pptx
AutoCAD Herramientas para el futuro, Juan Fandiño
trabajo programacion.docxxdxxxddxdxxdxdxxxdxxdxdxd
Clase 3 - Presentación visual (Insertando objetos visuales) POWER POINT.pdf
ORIGEN DE LA IA - GRADO 1102 INTELIGENCIA
sistemas de informacion.................

Programacion en C++ para Ciencia e Ingeniería

  • 1. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Programaci´on en C++ para Ciencia e Ingenier´ıa Mario Storti, Lisandro Dalc´ın, Rodrigo Paz http://www.cimec.org.ar/prog Facultad de Ingenier´ıa y Ciencias H´ıdricas Universidad Nacional del Litoral http://www.unl.edu.ar Centro de Investigaci´on de M´etodos Computacionales - CIMEC INTEC, (CONICET-UNL), http://www.cimec.org.ar Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 1 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 2. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Autores • Mario Storti <mario.storti@gmail.> • Lisandro Dalc´ın, <dalcinl@gmail.com> • Rodrigo Paz, <rodrigo.r.paz@gmail.com> Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 2 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 3. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Contents • slide 11.....Elementos b´asicos de programaci´on slide 13.....Compilaci´on vs. int´erpretes slide 14.....El proceso de compilaci´on slide 16.....El preprocesador CPP slide 19.....Chequeo de tipos slide 20.....Compilaci´on por separado slide 22.....Declaraciones y definiciones slide 24.....Definiciones y declaraciones de variables slide 26.....Incluyendo headers slide 29.....Usando librer´ıas slide 30.....Formato de include para C++ slide 31.....Un primer programa en C++ slide 32.....Namespaces slide 35.....Estructura de un programa slide 37.....Hello world slide 38.....Concatenaci´on de arreglos de caracters slide 39.....Entrada de datos slide 40.....Llamando a otros programas Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 3 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 4. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz slide 41.....Strings de C slide 42.....Strings de C++ slide 44.....Escribir y leer de archivos slide 46.....La clase vector slide 49.....Ejercicios • slide 50.....El C en C++ slide 51.....Funciones slide 52.....Valores de retorno slide 54.....Usando la librer´ıa est´andar de C slide 55.....Control de ejecuci´on. True and False slide 57.....If-else slide 61.....while slide 64.....do-while slide 65.....Lazo for slide 66.....Break and continue slide 68.....La sentencia switch slide 70.....goto slide 72.....Recursion slide 74.....Operadores slide 75.....Operadores de auto incremento slide 77.....Tipos de datos Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 4 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 5. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz slide 80.....Especificadores slide 84.....Punteros slide 94.....Referencias slide 96.....Punteros a void slide 98.....Scope de las variables slide 100.....Definiendo variables on-the-fly slide 104.....Variables locales slide 108.....Punteros a variables locales slide 109.....Variables est´aticas slide 111.....Constantes slide 112.....Operadores. Asignaci´on slide 113.....Operadores matem´aticos slide 114.....Operadores relacionales slide 115.....Operadores l´ogicos slide 116.....El operador hook slide 117.....Errores comunes con los operadores slide 118.....Operadores de cast slide 119.....Operador sizeof slide 120.....typedef: Aliases de tipos slide 121.....Estructuras slide 125.....Arrow operator Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 5 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 6. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz slide 126.....Enum’s slide 129.....Arreglos de estructuras slide 130.....Punteros y arreglos slide 132.....Arreglos de punteros slide 136.....Aritm´etica de punteros slide 138.....Tama˜nos de estructuras • slide 139.....Programaci´on Orientada a Objetos slide 140.....Abstracci´on de datos slide 150.....POO b´asica slide 160.....Inclusion de headers slide 164.....Estructuras enlazadas slide 172.....M´as sobre scoping slide 173.....Tipos Abstractos de Datos (ADT) slide 174.....Ocultando la implementaci´on slide 176.....Control de acceso a los miembros slide 180.....Amistad (Friendship) slide 183.....Anidamiento (nesting) y amistad slide 184.....Object layout slide 185.....Clases slide 189.....Ocultando totalmente la implementaci´on slide 191.....Inicializaci´on y cleanup Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 6 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 7. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz slide 193.....El constructor slide 194.....El destructor slide 197.....Eliminaci´on del bloque de definici´on slide 199.....Clase stash con ctor/dtor slide 203.....Stack con ctor/dtor slide 206.....Initializaci´on de agregados slide 207.....Inicializaci´on de estructuras slide 208.....Sobrecarga de funciones slide 212.....Argumentos por default slide 213.....Constantes slide 216.....Punteros a arreglos constantes de caracteres slide 217.....Const en argumentos de funciones slide 218.....Const en clases slide 219.....Objetos const y funciones de la clase • slide 221.....Chapter 5 slide 222.....Funciones inline slide 226.....Especificaciones de linkedicion slide 228.....Referencias en C++ slide 234.....Reglas para las referencias slide 236.....Paso por referencia y por copia slide 237.....El constructor por copia Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 7 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 8. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz slide 238.....Sobrecarga de operadores slide 243.....Sobrecarga de operadores unarios slide 251.....Sobrecarga de operadores binarios • slide 273.....Chapter slide 274.....Otros operadores que se pueden sobrecargar slide 275.....Creaci´on din´amica de objetos slide 276.....Uso de la memoria din´amica en C slide 277.....Uso de la memoria din´amica en C++ slide 279.....Porqu´e usar new y no arreglos slide 280.....Memory exhaust slide 281.....Composici´on slide 283.....Composici´on y la cadena de inicializaci´on slide 284.....Herencia slide 287.....Redefinici´on de m´etodos slide 289.....Herencia protegida slide 291.....Upcasting slide 292.....Polimorfismo slide 294.....Ejemplo polimorfismo. Integral 1D/2D/3D slide 298.....Clase que calcula integral 1D slide 300.....Integral 2D. Versi´on cruda slide 315.....Integral 2D. Versi´on mejorada Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 8 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 9. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz slide 318.....Integral 3D slide 321.....Integral 1D/2D/3D. User code slide 323.....Polimorfismo: ej. suma de los elementos de un vector slide ??.....Ejemplo clase vector sparse • slide 326.....Contenedores de la librer´ıa STL slide 328.....La librer´ıa STL slide 328.....La clase vector slide 333.....Algoritmos in-place slide 335.....La clase list slide 338.....La clase set slide 342.....La clase map slide 345.....Algoritmos slide 347.....Programaci´on funcional Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 9 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 10. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Dictado • Docentes de la c´atedra: Mario Storti <mario.storti@gmail.> Lisandro Dalc´ın, <dalcinl@gmail.com> Rodrigo Paz, <rodrigo.r.paz@gmail.com> Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 10 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 11. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Elementos b´asicos de programaci´on Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 11 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 12. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz I KNOW C++! Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 12 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 13. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Compilaci´on vs. int´erpretes • Algunos lenguajes de programaci´on tienen un int´erprete, por ejemplo Matlab/Octave, Python, Perl, Lisp/Scheme. En un int´erprete el usuario va emitiendo comandos que son interpretados por el int´erprete y va devolviendo un resultado. • Por contraposici´on, los lenguajes compilados el usuario escribe un archivo con l´ıneas de c´odigo, el cu´al es procesado por un compilador, que genera c´odigo de m´aquina, el cual es ejecutado directamente por el procesador. • Ventajas de la compilaci´on: el c´odigo suele ser m´as r´apido, y m´as compacto. • Desventajas: el paso de c´odigo a ejecutarlo es inmediato, no hay pasos intermedios. Usualmente los int´erpretes permiten escribir tareas que se repiten com´unmente en archivos de texto (scripts). El usuario puede adem´as mezclar estas funciones con comandos directamente en el int´erprete. Tambi´en con los int´erprete es m´as f´acil debuggear. • C++ es un lenguaje compilado. Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 13 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 14. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz El proceso de compilaci´on • El caso m´as simple es cuando todo el c´odigo del programa est´a en un s´olo archivo fuente: 1 $$ g++ -o prog prog.cpp Genera un archivo ejecutable prog. • Si el programa es muy grande conviene dividirlo en varias partes, en ese caso 1 $$ g++ -o prog prog1.cpp prog2.cpp • Esto requiere recompilar cada vez todos los *.cpp, si son muchos conviene hacer 1 $$ g++ -o prog1.o -c prog1.cpp 2 $$ g++ -o prog2.o -c prog2.cpp 3 $$ g++ -o prog prog1.o prog2.o Los archivos .o son objeto, contienen c´odigo de m´aquina. (No tiene relaci´on con la Programaci´on Orientada a Objetos). Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 14 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 15. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz El proceso de compilaci´on (cont.) • Si solo se modifica uno de los archivos (prog1.cpp), entonces s´olo hace falta recompilar ese. 1 $$ g++ -o prog1.o -c prog1.cpp 2 $$ g++ -o prog prog1.o prog2.o • Para mejor organizaci´on, si hay muchos *.o conviene ponerlos en una librer´ıa 1 $$ g++ -o prog1.o -c prog1.cpp 2 $$ g++ -o prog2.o -c prog2.cpp 3 $$ g++ -o prog3.o -c prog3.cpp 4 $$ ar r libprog.a prog1.o prog2.o prog3.o 5 $$ g++ -o prog main.cpp libprog.a • A veces la librer´ıa puede ser que haya sido desarrollada por un tercero: libpetsc.a, libmkl.a. Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 15 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 16. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz El preprocesador CPP • Muchas veces hay texto que se repite muchas veces en el c´odigo. En ese caso se pueden usar macros 1 int v[100000]; 2 if (n<100000) { 3 . . . . 4 } Se puede simplificar de la siguiente forma 1 #define MAX 100000 2 int v[MAX]; 3 if (n<MAX) { 4 . . . . 5 } Estos macros son manejados por el preprocesador, el cual se llama normalmente cpp (por C preprocesor). Podemos pensar que el CPP genera un paso intermedio en el cual toma el archivo prog.cpp y genera un archivo intermedio tempo.cpp que es el que finalmente es compilado. Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 16 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 17. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz El preprocesador CPP (cont.) • CPP s´olo realiza manipulaciones a nivel de texto, no conoce nada espec´ıfico del lenguaje C/C++, incluso puede usarse (y se usa) para otros lenguajes como Fortran. • Las directivas m´as usuales son 1 // Incluye todo el texto del archivo library.h 2 #include <library.h> 3 4 #define CHECK(a,n) if (a>n) error() • Para #include el preprocesador simplemente incluye todo el archivo mencionado en el punto donde se invoca el include. • #define define un macro, despu´es se puede llamar al macro en otros lugares del c´odigo y es reemplazado por su expansi´on. Los macros pueden tener argumentos. Por convenci´on se suele dar a los macros nombres en may´usculas. • Se puede conocer cual es el resultado del CPP llamando a g++ con la opci´on -E 1 $$ g++ -o tempo.cpp -E prog.cpp • El CPP es un programa separado que se puede llamar por s´ı mismo Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 17 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 18. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz (/usr/bin/cpp). Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 18 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 19. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Chequeo de tipos • C++ es un lenguaje tipado (aka tipeo est´atico, en ingl´es typed language), es decir las variables tienen tipos definidos. El compilador chequea que los resultados de las expresiones que se asignan a las variables correspondan al tipo con el cual fueron definidas, caso contrario se produce un error en tiempo de compilaci´on. Esto es bueno porque permite detectar tempranamente errores. (Es equivalente al chequeo de unidades en F´ısica). 1 // error: asigna un string a una variable entera 2 int a; 3 a = "Hello"; • Otros lenguajes (sobre todos los interpretados) hacen chequeo din´amico de tipo, esto implica una p´erdida de eficiencia. • El chequeo se hace tambi´en para los argumentos de una funci´on 1 void fun(int a,string s); 2 . . . 3 fun(23,45); // ERROR (45 no es un string!) Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 19 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 20. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Compilaci´on por separado • En C++ se favorece que un programa grande se pueda dividir en fracciones m´as peque˜nas. El mecanismo fundamental para dividir un programa en partes m´as peque˜nas es usar funciones que realizan tareas bien definidas. Por ejemplo podemos pensar en una funci´on int gcd(int,int); que toma dos enteros y retorna el m´aximo com´un divisor de los mismos. • Las funciones tienen argumentos, una vez que la funci´on termina su tarea, retorna un valor. Tambi´en puede ser que las funciones tengan efectos colaterales (side effects) es decir que modifiquen sus argumentos u otros objetos. Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 20 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 21. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Compilaci´on por separado (cont.) • Para crear un programa que est´e dividido en varios archivos, el c´odigo de un archivo debe poder usar las funciones del otro. Supongamos que un archivo prog1.cpp contiene a la funci´on gcd(). Si queremos usar a gcd() en el c´odigo de otro archivo prog2.cpp entonces el compilador debe estar seguro que el tipo de los argumentos que se le van a pasar son los correctos. Para eso hay que declarar a la funci´on en prog2.cpp antes de poder llamarla 1 int gcd(int,int); // declara gcd() 2 . . . 3 r = gcd(m,n); // la puede usar porque ya 4 // fue declarada Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 21 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 22. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Declaraciones y definiciones • Una declaraci´on le dice al compilador que esa funci´on existe y su prototipo o signatura, es decir el tipo de argumentos de entrada y de salida. Por ejemplo 1 int gcd(int,int); • La definici´on por otra parte dice espec´ıficamente como la funci´on realiza su tarea 1 int gcd(int x, int y) { 2 int a = x, b = y; 3 if (b>a) { 4 a = y; b = x; 5 } 6 while (true) { 7 int c = a % b; 8 if (c==0) return b; 9 a = b; b = c; 10 } 11 } Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 22 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 23. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Declaraciones y definiciones (cont.) • Cada funci´on puede estar declarada varias veces en un archivo (mientras la signatura de la funci´on sea la misma en cada una de las declaraciones). 1 int f(int x); 2 . . . 3 int f(int); // OK, misma signatura • Por el contrario, la funci´on s´olo puede estar definida una sola vez en todos los archivos del programa, ya que si no el compilador no sabr´ıa cual usar. 1 // archivo prog1.cpp 2 int f(int x) { return 2*x; } 3 4 // archivo prog2.cpp 5 int f(int x) { return 3*x; } 6 // -> ERROR: m´ultiplemente definida Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 23 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 24. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Definiciones y declaraciones de variables Si declaramos una variable, por ejemplo 1 int m; si bien parace una declaraci´on, en realidad ya tiene toda la informaci´on para construir al objeto (un entero de 4 bytes) por lo tanto el compilador lo toma adem´as como una definici´on. Por eso no podemos incluir dos veces esta declaraci´on/definici´on, aunque sea del mismo tipo. 1 int m; 2 . . . 3 int m; // ERROR Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 24 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 25. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Definiciones y declaraciones de variables (cont.) • Si queremos forzar a que sea una declaraci´on y no una definici´on entonces debemos usar el keyword extern 1 extern int m; 2 . . . 3 extern int m; // OK 4 . . . 5 int m; // OK • extern se puede usar tambi´en con las funciones, para hacer hincapi´e en que es una declaraci´on, por ejemplo 1 extern int f(int x); pero no es necesario. Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 25 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 26. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Incluyendo headers • Es usual que en nuestros programas escribamos una serie de funciones que despu´es utilizaremos en otras partes del programa. 1 // utils.cpp 2 int gcd(int m,int n) { /* . . . */ } 3 double cos(double alpha) { /* . . . */ } 4 double sin(double alpha) { /* . . . */ } 5 . . . • Cuando queremos usar estas funciones en otro archivo fuente prog.cpp primero tenemos que declararlas 1 // prog.cpp 2 int gcd(int m,int n); 3 double cos(double alpha); 4 double sin(double alpha); 5 . . . 6 int x = gcd(m,n); 7 double c = cos(alpha); 8 double s = sin(theta); 9 . . . Esto se vuelve muy engorroso si hay que incluir las declaraciones en cada Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 26 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 27. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz uno de los archivos prog1.cpp, prog2.cpp... y utils.cpp tiene cientos de funciones. Entonces para resolver esto incluimos todas las declaraciones en un archivo header (cabecera) utils.h: 1 // utils.h 2 int gcd(int m,int n); 3 double cos(double alpha); 4 double sin(double alpha); Entonces despu´es en prog1.cpp hay que solo incluir el header: 1 // prog1.cpp 2 #include "utils.h" 3 . . . 4 int x = gcd(m,n); 5 double c = cos(alpha); 6 double s = sin(theta); 7 . . . Recordemos que lo que ocurre es que el preprocesador CPP se encarga de buscar el archivo header y crear un archivo temporario donde la linea del include es reemplazada por los contenidos del archivo. Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 27 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 28. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Incluyendo headers (cont.) Hay dos versiones de include, • Una que especifica archivos en forma relativa o absoluta 1 #include ". ./utils.h" 2 #include "utils2.h" 3 #include "/usr/include/utils3.h" 4 . . . • Otra que busca los headers en una serie de directorios que el usuario define en el comando de compilaci´on 1 $$ g++ -I/home/mstorti/utils -c -o prog.o prog.cpp 1 // lo encuentra en /home/mstorti/utils 2 #include <utils4.h> 3 // lo encuentra en /home/mstorti/utils/src 4 #include <src/utils5.h> 5 . . . Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 28 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 29. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Usando librer´ıas • Entonces si tengo que usar una librer´ıa matrix que est´a compuesta de varios archivos fuente matrix2.cpp, matrix1.cpp, matrix3.cpp... en realidad no hace falta que compile todos estos archivos, mientras que el desarrollador de esa librer´ıa provea Un archivo libmatrix.a con todos los matrix<n>.cpp compilados. Un archivo header con las declaraciones de las funciones matrix.h. • Entonces para usar la librer´ıa basta con incluir el header 1 // myprog.cpp 2 #include <matrix.h> 3 . . . y al linkeditar incluir la librer´ıa 1 $$ g++ myprog.cpp /usr/lib/libmatrix.a -o myprog Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 29 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 30. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Formato de include para C++ • La extensi´on que se usa para los archivos fuente puede ser .cpp, .cxx. Para los headers se utiliza .h, .hpp, .hxx. • Para evitar confusiones y ambig¨uedad con las extensiones, C++ introdujo el concepto de include sin extensi´on. El traductor se encarga de convertir el nombre y buscar la extensi´on. 1 #include <matrix> • Existe una librer´ıa con muchas funciones muy ´utiles que es est´andar de C y se llama justamente libc.a. Entre otras incluye funciones Matem´aticas math.h: round, cos, sin, floor, ceil, ... Input/output stdio.h: printf, scanf, read, write, stdlib.h: rand, system, ... En C++ estos headers es mejor incluirlos sin el .h y con una c: 1 #include <stdio.h> // C 2 #include <cstdio> // C++ Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 30 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 31. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Un primer programa en C++ • Para imprimir por terminal hay que usar el operador << de la clase iostream: 1 #include <iostream> 2 . . . 3 cout << "Hola"; El operador << en C quiere decir en realidad otra cosa: es para desplazar los bits en un n´umero entero. Pero C++ permite redefinir los operadores (lo que se llama sobrecarga de operadores) de manera que en este contexto << quiere decir “enviar a”. Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 31 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 32. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Namespaces • A medida que una librer´ıa o programa crecen cada vez hay m´as funciones y es muy posible que se produzca la colisi´on de nombres. Por ejemplo, si escribo una librer´ıa para manipular matrices, puedo querer implementar una funci´on rand() que llena la matriz con n´umeros aleatorios. Lamentablemente la libc ya usa el nombre rand() para generar un ´unico numero aleatorio. • Una soluci´on que se usaba en C era prependizar un prefijo identificador de la librer´ıa a todas las funciones de la misma matrix_rand(), matrix_sum(), matrix_prod(). Esto se vuelve muy engorroso. Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 32 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 33. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Namespaces (cont.) • C++ provee un mecanismo para evitar colisiones llamado namespaces. Todos los archivos de la librer´ıa se incluyen en un namespace de la siguiente forma 1 // matrix.cpp 2 namespace matrix { 3 void rand(. . .) { /* . . . */ } 4 double sum(. . .) { /* . . . */ } 5 void prod(. . .) { /* . . . */ } 6 } • Entonces despu´es las funciones se deben llamar con el operador de scope ::: por ejemplo matrix::rand(). • Si en un archivo fuente se va a utilizar mucho una librer´ıa entonces puede incluir todo el namespace, de manera que no hay que hacer el scope 1 // prog.cpp 2 using namespace matrix; 3 4 rand(A); 5 double m = max(A); Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 33 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 34. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Namespaces (cont.) • Muchas utilidades y variables est´andar de C++, por ejemplo cout, est´an en el namespace std de manera que o bien hay que hacer 1 std::cout << "Hola"; o si no 1 using namespace std; 2 . . . 3 cout << "Hola"; Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 34 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 35. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Estructura de un programa • Un programa en C/C++ est´a compuesto de una colecci´on de funciones y variables. Cuando uno lanza el programa hay que determinar d´onde se empieza a ejecutar el c´odigo, o sea el punto de entrada. En C/C++ el punto de entrada es la funci´on main(). • La definici´on de una funci´on consiste en un valor de retorno, el nombre de la funci´on y su lista de argumentos. El cuerpo de la funci´on (las instrucciones que la componen) van entre llaves. 1 int function() { 2 // Function code here (this is a comment) 3 } • Puede haber m´as pares de llaves balanceadas ({}) adentro de la funci´on pero debe haber uno m´as externo que define el cuerpo de la funci´on. • Como main() es una funci´on, debe respetar estos requisitos. main() no tiene argumentos y retorna un int. Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 35 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 36. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Estructura de un programa (cont.) • C/C++ es un lenguaje de formato libre (free form), la indentaci´on o la posici´on de las variables en la l´ınea son irrelevantes. • Tampoco es relevante la cantidad espacio en blanco (espacios, tabs, fin de l´ınea). Cualquier cantidad de estos caracteres juntos es equivalente a un solo espacio. De hecho un programa en C++ podr´ıa escribirse ne una sola l´ınea. • En C los comentarios van encerrados entre /* y */ (comentario multil´ınea). En C++ se agreg´o un nuevo tipo de comentario que es por l´ınea desde un // hasta el final de la l´ınea. (Esto viola un poco el concepto de free form). 1 /* Comentario multilinea tipo C */ 2 int /* comentario en el medio del c´odigo */ x; 3 // Comentario por linea tipo C++ Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 36 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 37. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Hello world 1 // Saying Hello with C++ 2 #include <iostream> // Stream declarations 3 using namespace std; 4 5 int main() { 6 cout << "Hello, World. I am " 7 << 8 << " Today" << endl; 8 } • Le pasamos a cout una serie de elementos de diferentes tipos: enteros, arreglos de caracteres. • endl es un final de l´ınea. • En C se llama string a un pedazo de texto entre comillas. No confundir con la clase string de C++ que cumple funciones similares pero es mucho m´as potente. A los strings de C se los debe llamar m´as correctamente arreglos de caracteres. • Dentro del texto entre comillas se pueden incluir secuencias de escape que permiten incluir caracteres especiales con precedidos de una barra invertida: n es un caracter de fin de l´ınea, t un TAB, 0 un NULL, una barra invertida. Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 37 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 38. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Concatenaci´on de arreglos de caracters • Para incluir arreglos de caracteres muy largos se puede simplemente poner uno a continuaci´on de otro (puede ser en diferentes l´ıneas). El CPP se encarga de juntarlos todos en una sola l´ınea: "aaa" "bbbb" es completamente equivalente a "aaabbbb". 1 // Character array Concatenation 2 #include <iostream> 3 using namespace std; 4 5 int main() { 6 cout << "This is far too long to put on a " 7 "single line but it can be broken up with " 8 "no ill effectsnas long as there is no " 9 "punctuation separating adjacent character " 10 "arrays.n"; 11 } Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 38 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 39. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Entrada de datos cout es console output, cin es console input y permite ingresar datos. 1 // Converts decimal to octal and hex 2 #include <iostream> 3 using namespace std; 4 5 int main() { 6 int number; 7 cout << "Enter a decimal number: "; 8 cin >> number; 9 cout << "value in octal = 0" 10 << oct << number << endl; 11 cout << "value in hex = 0x" 12 << hex << number << endl; 13 } oct y hex son manipulators, cambian el estado de cout. Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 39 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 40. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Llamando a otros programas Dentro de la librer´ıa est´andar de C hay una funci´on muy potente system() que permite llamar a otros programas desde un programa en C/C++. Se le pasa un arreglo de caracteres con el comando que uno ejecutar´ıa en la l´ınea de comandos. 1 // Call another program 2 #include <cstdlib> // Declare ‘‘system()’’ 3 using namespace std; 4 5 int main() { 6 system("date -u"); 7 } Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 40 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 41. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Strings de C Manipular arreglos de caracteres en C se vuelve muy engorroso. 1 #include <iostream> 2 #include <cstring> 3 using namespace std; 4 5 int main() { 6 // concatenate two character arrays s1 and s2 7 char s1[ ] = "Hola "; 8 char s2[ ] = "mundo."; 9 cout << strlen(s1) << endl; 10 int n1 = strlen(s1); 11 int n2 = strlen(s2); 12 char *s = new char[n1+n2+1]; 13 strncpy(s,s1,n1); 14 strncpy(s+n1,s2,n2); 15 s[n1+n2] = ’0’; 16 cout << s << endl; 17 delete[ ] s; 18 return 0; 19 } Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 41 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 42. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Strings de C++ Para eso C++ tiene objetos llamados strings que permiten manipularlos en forma mucho m´as simple y con menor probabilidad de error. 1 #include <iostream> 2 #include <string> 3 using namespace std; 4 5 int main() { 6 // concatenate two character arrays s1 and s2 7 string s1 = "Hola "; 8 string s2 = "mundo."; 9 string s = s1 + s2; 10 cout << s << endl; 11 return 0; 12 } Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 42 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 43. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Strings de C++ (cont.) 1 //: C02:HelloStrings.cpp 2 // The basics of the Standard C++ string class 3 #include <string> 4 #include <iostream> 5 using namespace std; 6 7 int main() { 8 string s1, s2; // Empty strings 9 string s3 = "Hello, World."; // Initialized 10 string s4("I am"); // Also initialized 11 s2 = "Today"; // Assigning to a string 12 s1 = s3 + " " + s4; // Combining strings 13 s1 += " 8 "; // Appending to a string 14 cout << s1 + s2 + "." << endl; 15 } Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 43 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 44. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Escribir y leer de archivos • Las funciones est´an declaradas en el header <fstream>. • Para escritura hay que crear un objeto de tipo ofstream (como cout). • Para lectura hay que crear un objeto de tipo ifstream (como cin). • La funci´on getline(stream,s) lee una l´ınea de stream y la guarda en el string s 1 // Copy one file to another, a line at a time 2 #include <string> 3 #include <fstream> 4 using namespace std; 5 int main() { 6 ifstream in("Scopy.cpp"); // Open for reading 7 ofstream out("Scopy2.cpp"); // Open for writing 8 string s; 9 while(getline(in, s)) // Discards newline char 10 out << s << "n"; // . . . must add it back 11 } Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 44 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 45. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Escribir y leer de archivos (cont.) Otro ejemplo es guardar todo el archivo en un s´olo string: 1 // Read an entire file into a single string 2 #include <string> 3 #include <iostream> 4 #include <fstream> 5 using namespace std; 6 7 int main() { 8 ifstream in("FillString.cpp"); 9 string s, line; 10 while(getline(in, line)) 11 s += line + "n"; 12 cout << s; 13 } ¿Que pasa si queremos guardar cada l´ınea en un string separado? Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 45 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 46. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz La clase vector • Un vector es un contenedor que permite guardar un n´umero indefinido de elementos en forma contigua e indexada. • Se puede agrandar o achicar en forma din´amica, sin perder los elementos preexistentes. • Est´a templatizado o sea que se pueden definir vectores de diferentes tipos: vector<int>, vector<double>, vector<string>,... • La funci´on push_back() permite agregar un nuevo objeto al final del vector. Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 46 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 47. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz La clase vector (cont.) 1 // Copy an entire file into a vector of string 2 #include <string> 3 #include <iostream> 4 #include <fstream> 5 #include <vector> 6 using namespace std; 7 8 int main() { 9 vector<string> v; 10 ifstream in("Fillvector.cpp"); 11 string line; 12 while(getline(in, line)) 13 v.push-back(line); // Add the line to the end 14 // Add line numbers: 15 for(int i = 0; i < v.size(); i++) 16 cout << i << ": " << v[i] << endl; 17 } Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 47 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 48. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz La clase vector (cont.) vector tambi´en puede guardar cualquier otro tipo, por ejemplo enteros: 1 // Creating a vector that holds integers 2 #include <iostream> 3 #include <vector> 4 using namespace std; 5 6 int main() { 7 vector<int> v; 8 for(int i = 0; i < 10; i++) 9 v.push-back(i); 10 for(int i = 0; i < v.size(); i++) 11 cout << v[i] << ", "; 12 cout << endl; 13 for(int i = 0; i < v.size(); i++) 14 v[i] = v[i] * 10; // Assignment 15 for(int i = 0; i < v.size(); i++) 16 cout << v[i] << ", "; 17 cout << endl; 18 } Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 48 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 49. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Ejercicios 1. Crear un programa que abre un archivo y cuenta las palabras (separadas por whitespace). Ayuda: el operador >> lee de a palabras de un ifstream. 2. Crear un programa que cuenta la cantidad de caracteres que tiene un archivo. 3. Crear un programa que cuenta la cantidad de ocurrencias de una palabra espec´ıfica en un archivo. Ayuda: usar == para comparar strings. 4. Escribir un programa que imprime las l´ıneas de un archivo de texto en orden inverso. Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 49 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 50. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz El C en C++ Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 50 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 51. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Funciones • Para evitar errores, C/C++ usa el concepto de prototipo o signatura de funciones. • Antes de usar una funci´on hay que declararla. • Al usar la funci´on los argumentos con que es llamada deben coincidir con el el tipo que fueron declarados. 1 int translate(float x, float y, float z); 2 int translate(float, float, float); • En alg´un lugar la funci´on tiene que estar definida, aqu´ı los nombres de los argumentos tienen que aparecer para poder ser usados en la funci´on 1 int translate(float x, float y, float z) { 2 x = y = z; 3 // . . . 4 } Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 51 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 52. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Valores de retorno • La declaraci´on de la funci´on debe indicar el valor de retorno. Si la funci´on no retorna nada usar void: 1 int f1(void); // Returns an int, takes no arguments 2 int f2(); // Like f1() in C++ but not in Standard C 3 float f3(float, int, char, double); // Returns a float 4 void f4(void); // Takes no arguments, returns nothing • Para retornar el valor usar la sentencia return. • Si la funci´on retorna void entonces no se debe llamar a return. • Se puede tener m´as de un return en la funci´on. Son puntos de salida. • El valor de retorno debe ser compatible con el indicado en la declaraci´on. Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 52 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 53. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Valores de retorno (cont.) 1 // Use of ‘‘return’’ 2 #include <iostream> 3 using namespace std; 4 5 char cfunc(int i) { 6 if(i == 0) 7 return ’a’; 8 if(i == 1) 9 return ’g’; 10 if(i == 5) 11 return ’z’; 12 return ’c’; 13 } 14 15 int main() { 16 cout << "type an integer: "; 17 int val; 18 cin >> val; 19 cout << cfunc(val) << endl; 20 } ///:˜ Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 53 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 54. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Usando la librer´ıa est´andar de C • C incluye una librer´ıa de funciones est´andar (tambi´en llamada libc). Todos los compiladores que satisfacen la norma deben incluir estas funciones en su libc. Esto permite la portabilidad de los programas entre diferentes compiladores. • Muchos compiladores incluyen funciones adicionales que NO est´an en la norma. Por lo tanto hay que prever que si se lleva el proyecto a otra plataforma puede ser que estas funciones no existan en esa plataforma. • La documentaci´on de las librer´ıas usualmente incluye la declaraci´on de la funci´on y en que header (archivo .h) est´a. • En caso que la librer´ıa no est´e documentada hay que directamente ver los headers para encontrarel prototipo de la funci´on. Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 54 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 55. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Control de ejecuci´on. True and False • Todas los condicionales (por ejemplo if o while) usan expresiones l´ogicas como por ejemplo el resultado del operador de comparaci´on A==B. Esta expresi´on retorna directamente un valor l´ogico true o false. No confundiir con el operador de asignaci´on A=B. • Lo mismo ocurre con otros operadores de comparaci´on 1 A==B; //It’s equal? 2 A!=B; //It’s distinct? 3 A<B; //It’s smaller? 4 A<=B; //It’s smaller or equal? 5 A>B; //It’s greater? 6 A>=B; //It’s greater or equal? Si la expresi´on no retorna un valor booleano, entonces C trata de convertirlo. Para todos los valores num´ericos (enteros, float, double, char, punteros) el valor es falso si es cero, y en cualquier otra caso es verdadero. Entonces por ejemplo el valor l´ogico de las siguientes expresiones es equivalente 1 if (n) { . . . } 2 if (n!=0) { . . . . } Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 55 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 56. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz 3 if (!(n==0)) { . . . . } // ! is negation Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 56 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 57. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz If-else El if puede existir de dos formas, con o sin else 1 if (expression) 2 statement 3 4 // o 5 6 if (expression) 7 statement 8 else 9 statement En ambos casos statement puede ser una sentencia simple, terminada en una coma, o compuesta, es decir un bloque de instrucciones encerrado en {}. 1 if (n>0) x=23; // sentencia simple 2 3 if (n>0) { // sentencia compuesta 4 x=23; 5 s="haha"; 6 } Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 57 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 58. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz If-else (cont.) 1 int i; 2 cout << "type a number and ’Enter’" << endl; 3 cin >> i; 4 if(i > 5) 5 cout << "It’s greater than 5" << endl; 6 else 7 if(i < 5) 8 cout << "It’s less than 5 " << endl; 9 else 10 cout << "It’s equal to 5 " << endl; 11 12 cout << "type a number and ’Enter’" << endl; 13 cin >> i; 14 if(i < 10) 15 if(i > 5) // ‘‘if’’ is just another statement 16 cout << "5 < i < 10" << endl; 17 else 18 cout << "i <= 5" << endl; 19 else // Matches ‘‘if(i < 10)’’ 20 cout << "i >= 10" << endl; Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 58 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 59. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz If-else (cont.) Notar que todo el if act´ua como una sola instrucci´on, por eso no hace falta encerrarlo con un {}. 1 if(i > 5) 2 cout << "It’s greater than 5" << endl; 3 else 4 if(i < 5) 5 cout << "It’s less than 5 " << endl; 6 else 7 cout << "It’s equal to 5 " << endl; 8 9 // es equivalente a 10 11 if(i > 5) { cout << "It’s greater than 5" << endl; } 12 else { 13 if(i < 5) 14 cout << "It’s less than 5 " << endl; 15 else 16 cout << "It’s equal to 5 " << endl; 17 } Es una convenci´on mut ´util indentar ambos bloques del if para mejorar la Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 59 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 60. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz legibilidad. Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 60 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 61. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz while while, do-while y for controlan lazos (loops) de ejecuci´on. 1 while(expression) 2 statement Como antes statement puede ser simple o compuesto. La expresi´on se eval´ua hasta que la condici´on de falso. Para que el lazo termine en alg´un momento es necesario que statement tenga alg´un efecto que haga que eventualmente expression de falso 1 int x=0; 2 while (x<5) x=34; // ejecuta una vez el lazo 3 x=0; 4 while (x<5) x=2; // ejecuta indefinidamente 5 6 x=0; 7 while (x<5) x++; // ejecuta el bloque 5 veces Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 61 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 62. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz while (cont.) 1 // Guess a number (demonstrates ‘‘while’’) 2 #include <iostream> 3 using namespace std; 4 5 int main() { 6 int secret = 15; 7 int guess = 0; 8 // != is the not-equal conditional: 9 while(guess != secret) { // Compound statement 10 cout << "guess the number: "; 11 cin >> guess; 12 } 13 cout << "You guessed it!" << endl; 14 } Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 62 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 63. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz while (cont.) En C la condici´on dentro del condicional puede ser tan elaborada como se quiera, la ´unica restricci´on es que debe retornar un valor l´ogico (o convertible a l´ogico), incluso puede ser que el cuerpo del lazo este vac´ıo 1 while(do-a-lot-of-work()) ; 2 while(do-a-lot-of-work()) { } por ejemplo 1 while(is-prime(n)) n++; // busca el primer n no primo Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 63 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 64. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz do-while 1 do 2 statement 3 while(expression); Es similar al while pero ahora statement es ejecutado antes de verificar la condici´on. 1 n=0; 2 while (n>0) /* body. . .*/ ; // body is not executed 3 4 n=0; 5 do 6 /* body. . .*/ ; // body is executed once 7 while (n>0); Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 64 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 65. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Lazo for La forma del for es 1 for(initialization; conditional; step) 2 statement Se utiliza mucho cuando simplemente se quiere ejecutar un bloque una serie de veces bien definida 1 for (int i=0; i<n; i++) { 2 // This block is executed n times 3 } Esto es completamente equivalente a 1 int i=0; 2 while(i<n) { 3 // This block is executed n times 4 i++; 5 } Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 65 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 66. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Break and continue Adentro de cualquiera de los bloques while, do-while o for se puede usar break para salir del lazo inmediatamente. 1 while (true) { // Infinite loop 2 cout << "Enter a number: "; 3 cin >> n; 4 if (is-prime(n)) break; 5 cout << n << " es un n´umero compuesto" << endl; 6 } Si hay m´as de un lazo anidado entonces break sale del lazo m´as interno 1 for (int i=0; i<n; i++) { 2 for (int j=0; j<n; j++) { 3 if (j>i*i) break; 4 //. . . 5 } 6 // break transfers execution here 7 } Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 66 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 67. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Break and continue (cont.) continue es similar a break pero hace que se ejecute la siguiente iteraci´on del lazo 1 for (int j=0; j<n; j++) { 2 //. . . . 3 if (!is-prime(j)) continue; 4 // do this only for primes. . . 5 } Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 67 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 68. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz La sentencia switch Va comparando la variable selector hasta que coincide con uno de los case 1 switch(selector) { 2 case integral-value1 : statement; break; 3 case integral-value2 : statement; break; 4 case integral-value3 : statement; break; 5 case integral-value4 : statement; break; 6 case integral-value5 : statement; break; 7 (. . .) 8 default: statement; 9 } por ejemplo 1 char c; 2 //. . . 3 switch (c) { 4 case ’a’: cout << "It’s an a" << endl; break; 5 case ’b’: cout << "It’s a b" << endl; break; 6 default: cout << "Neither a or b" << endl; 7 } Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 68 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 69. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Si no se incluyen los break entonces la ejecuci´on sigue al siguiente case. Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 69 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 70. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz goto La sentencia goto permite saltar a otro punto del programa. Se lo considera muchas veces como una mala pr´actica de programaci´on, aunque a veces puede ser ´util, por ejemplo para saltar de varios lazos anidados cuando se encuentra una condici´on. 1 // The infamous goto is supported in C++ 2 #include <iostream> 3 using namespace std; 4 5 int main() { 6 long val = 0; 7 for(int i = 1; i < 1000; i++) { 8 for(int j = 1; j < 100; j += 10) { 9 val = i * j; 10 if(val > 47000) 11 goto bottom; 12 // Break would only go to the outer ’for’ 13 } 14 } 15 bottom: // A label 16 cout << val << endl; Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 70 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 71. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz 17 } Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 71 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 72. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Recursion Muchos problemas son intr´ınsecamente recursivos, es decir la soluci´on de un problema est´a dada por la soluci´on de uno menor con el mismo algoritmo, por ejemplo la definici´on de factorial se puede hacer en forma recursiva n! = n · (n − 1)! (1) en realidad esto es cierto si n > 1, la definici´on correcta es n! =    1; si n = 1; n · (n − 1)! ; si n > 1 (2) decimos que el caso n = 1 corta la recursi´on. Usando llamadas recursivas a funciones podemos implementar la funci´on factorial 1 int factorial(int n) { 2 if (n==1) return 1; 3 else return n*factorial(n-1); 4 } Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 72 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 73. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Recursion (cont.) La recursi´on es muy elegante para resolver problemas, pero puede ser demandante en t´erminos de recursos. Es m´as simple si calculamos el factorial con un lazo 1 int factorial(int n) { 2 int fac=1; 3 for (int j=2; j<=n; j++) fac *= j; 4 return fac; 5 } El operador *= quiere decir aqu´ı 1 fac = fac*j; Se puede aplicar a otros operadores binarios como +*-/, operadores l´ogicos ||&&, concatenaci´on de strings... Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 73 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 74. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Operadores Los operadores no son m´as que funciones, con una sintaxis especial. Un operador toma una o m´as series de valores y devuelve un resultado. 1 a = b + c; podemos pensar que es traducido por el compilador en 1 a = sum(b,c); Una cuesti´on importante con los operadores es la precedencia de los mismos. Para los operadores matem´aticos es similar a las reglas que aprendemos en la escuela 1 a = b * c + d; es equivalente a 1 a = (b * c) + d; porque * tiene mayor precedencia que +. Ante la duda, se pueden introducir par´entesis para forzar el orden en que se eval´uan las expresiones. Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 74 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 75. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Operadores de auto incremento El operador ++ es un atajo para una operaci´on muy com´un en programaci´on: incrementar una variable de tipo entero en una unidad. Hay dos variantes, prefija y postfija, ambos tienen el mismo efecto colateral (incrementar la variable) pero en el prefijo retorna el valor de la variable incrementada, y el postfijo sin incrementar 1 int m,n=5; 2 m = n++; // n=6, m=5 3 4 int m,n=5; 5 m = ++n; // n=6, m=6 Por ejemplo la siguiente funci´on retorna el primer primo siguiente (mayor o igual) a n. 1 int next-prime(int n) { 2 while (!is-prime(n++)) { } 3 return n; 4 } Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 75 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 76. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Operadores de auto incremento (cont.) Tambi´en hay autodecremento -- prefijo y postfijo. 1 int n=10; 2 while (n >= 0) cout << n-- << ", "; 3 cout << "Boom!!" << endl; 1 [mstorti@galileo garage]$$ ./boom.bin 2 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, Boom!! Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 76 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 77. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Tipos de datos Dijimos que C/C++ es un lenguaje de tipeo est´atico, es decir en el momento de crear las variables hay que decir de que tipo son. Hay tipos de datos built-in como enteros, floats, strings, que ya est´an definidos en el compilador, y tambi´en el programador puede crear sus propios tipos, muchas veces por composici´on. Por ejemplo si estamos creando la base de datos de una empresa podemos querer tener un tipo de dato employee que contenga un string (el nombre), un entero (el n´umero de empleado) y un float (el sueldo). Los tipos built-in son • char un entero de al menos 8 bits, usualmente se usa para almacenar caracteres. • int un entero de al menos 16 bits (2 bytes) • float un n´umero de punto flotante con al menos 4 bytes (simple precisi´on) • double un n´umero de punto flotante con al menos 8 bytes (doble precisi´on). Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 77 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 78. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Tipos de datos (cont.) 1 // Defining the four basic data 2 // types in C and C++ 3 4 int main() { 5 // Definition without initialization: 6 char protein; 7 int carbohydrates; 8 float fiber; 9 double fat; 10 // Simultaneous definition & initialization: 11 char pizza = ’A’, pop = ’Z’; 12 int dongdings = 100, twinkles = 150, 13 heehos = 200; 14 float chocolate = 3.14159; 15 // Exponential notation: 16 double fudge-ripple = 6e-4; 17 } Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 78 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 79. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Tipos de datos (cont.) Como los tipos b´asicos tienen una cantidad de bits fija pueden representar un tama˜no m´aximo. Por ejemplo los enteros de 16 bits s´olo pueden estar entre -32768 y +32768. Adem´as el tama˜no del tipo (la cantidad de bits) puede depender de la m´aquina y del compilador, entonce los valores m´aximos y m´ınimos (los l´ımites) est´an definidos en headers float.h y limits.h, 1 #include <climits> 2 3 cout << "Minimum and maximum integers are " 4 << endl << INT-MIN << " and " << INT-MAX 5 << endl; 6 } 1 [mstorti@galileo garage]$$ ./intmax.bin 2 Minimum and maximum integers are 3 -2147483648 and 2147483647 Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 79 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 80. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Especificadores • Para representar enteros se utiliza un bit de los 32 disponibles para representar el signo. • Si s´olo se van a utilizar enteros positivos entonces podemos usar ese bit para extender un factor 2 el rango. • int en el rango [-2147483648,2147483647] • unsigned int en el rango [0,4294967295] unsigned es un specifier, otros son: signed, unsigned, short, long. Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 80 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 81. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Especificadores (cont.) 1 //: C03:Specify.cpp 2 // Demonstrates the use of specifiers 3 #include <iostream> 4 using namespace std; 5 6 int main() { 7 char c; 8 unsigned char cu; 9 int i; 10 unsigned int iu; 11 short int is; 12 short iis; // Same as short int 13 unsigned short int isu; 14 unsigned short iisu; 15 long int il; 16 long iil; // Same as long int 17 unsigned long int ilu; 18 unsigned long iilu; 19 float f; 20 double d; 21 long double ld; Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 81 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 82. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz 22 cout 23 << "n char= " << sizeof(c) 24 << "n unsigned char = " << sizeof(cu) 25 << "n int = " << sizeof(i) 26 << "n unsigned int = " << sizeof(iu) 27 << "n short = " << sizeof(is) 28 << "n unsigned short = " << sizeof(isu) 29 << "n long = " << sizeof(il) 30 << "n unsigned long = " << sizeof(ilu) 31 << "n float = " << sizeof(f) 32 << "n double = " << sizeof(d) 33 << "n long double = " << sizeof(ld) 34 << endl; 35 } ///:˜ Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 82 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 83. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Especificadores (cont.) 1 [mstorti@galileo garage]$$ ./sizes.bin 2 3 char= 1 4 unsigned char = 1 5 int = 4 6 unsigned int = 4 7 short = 2 8 unsigned short = 2 9 long = 8 10 unsigned long = 8 11 float = 4 12 double = 8 13 long double = 16 14 [mstorti@galileo garage]$$ Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 83 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 84. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Punteros Al declarar variables lo que estamos haciendo es dar un nombre a un pedazo de la memoria. Cuando decimos int n lo que estamos diciendo al compilador es: res´erveme 4 bytes de la memoria y a partir de ahora lo voy a llamar n. El operador & nos muestra en que posici´on de la memoria fue alocada la variable 1 int n; 2 cout << "variable n is in position " << &n << endl; 1 [mstorti@galileo garage]$$ ./ptr.bin 2 variable n is in position 0x7fff1c46d92c Los punteros son impresos normalmente en formato de hexadecimales, si quisi´eramos verlo en formato decimal podemos castear (convertir) el puntero a un entero 1 int n; 2 cout << "variable n is in position " << (long)&n << endl; 1 [mstorti@galileo garage]$$ ./ptr.bin 2 variable n is in position 140737075615260 Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 84 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 85. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Punteros (cont.) 1 #include <iostream> 2 using namespace std; 3 4 int dog, cat, bird, fish; 5 6 void f(int pet) { 7 cout << "pet id number: " << pet << endl; 8 } 9 10 int main() { 11 int i, j, k; 12 cout << "f(): " << (long)&f << endl; 13 cout << "dog: " << (long)&dog << endl; 14 cout << "cat: " << (long)&cat << endl; 15 cout << "bird: " << (long)&bird << endl; 16 cout << "fish: " << (long)&fish << endl; 17 cout << "i: " << (long)&i << endl; 18 cout << "j: " << (long)&j << endl; 19 cout << "k: " << (long)&k << endl; 20 } Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 85 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 86. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Punteros (cont.) El resultado es 1 [mstorti@galileo garage]$$ ./pointers.bin 2 f(): 4196630 3 dog: 6295956 4 cat: 6295960 5 bird: 6295964 6 fish: 6295968 7 i: 140736631158572 8 j: 140736631158568 9 k: 140736631158564 10 [mstorti@galileo garage]$$ Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 86 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 87. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Punteros (cont.) • La direcci´on en memoria de un variable puede cambiar de una corrida a otra. • Funciones, variables y globales parecen estar en sectores de la memoria diferentes. • Enteros parecen ocupar 4 bytes. • Las posiciones en la memoria se pueden guardar en una variable de tipo especial llamada puntero 1 int number; 2 int *number-p = &number; • El sufijo _p o simplemente p indica que es un puntero (es s´olo una convenci´on). Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 87 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 88. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Punteros (cont.) • Algunos programadores ponen el * junto al tipo. 1 int* number-p; Es totalmente equivalente, pero confuso, 1 int* number-p,n-p,m-p; Declara a number_p, pero n_p y m_p son declarados enteros. Lo correcto es 1 int *number-p,*n-p,*m-p; • Podemos asignar a una variable de tipo puntero la direcci´on de una variable, lo cual nos permite modificarla a trav´es de ese proxy 1 int number=100; 2 int *number-p = &number; 3 *number-p = 25; // Ahora number contiene 25!! Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 88 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 89. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Punteros (cont.) • OJO: el hecho de declarar una variable de tipo puntero no significa que est´e apuntando a un objeto v´alido, es deber del programador asignarle al puntero una posici´on v´alida, si no puede dar error en tiempo de ejecuci´on al querer usar el puntero. 1 int *p; 2 cout << "contenido de *p " << *p << endl; // ERROR 3 int x; 4 p = &x; 5 cout << "contenido de *p " << *p << endl; // OK Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 89 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 90. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Punteros (cont.) Los punteros tienen un mont´on de usos, el primero que veremos es el de causar que una funci´on modifique un objeto. El mecanismo de paso de variables en C/C++ es por copia. 1 #include <iostream> 2 using namespace std; 3 4 void f(int a) { 5 cout << "&a = " << &a << endl; 6 cout << "a = " << a << endl; 7 a = 5; 8 cout << "a = " << a << endl; 9 } 10 11 int main() { 12 int x = 47; 13 cout << "&x = " << &x << endl; 14 cout << "x = " << x << endl; 15 f(x); 16 cout << "x = " << x << endl; 17 } Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 90 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 91. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Punteros (cont.) Imprime: 1 [mstorti@galileo sources]$$ ./try40.bin 2 &x = 0x7ffe99dd33ec 3 x = 47 4 &a = 0x7ffe99dd33bc 5 a = 47 6 a = 5 7 x = 47 8 [mstorti@galileo sources]$$ x = 47 Como la variable a en f() es una copia, resulta que la modificaci´on que se hace en f() no persiste, de manera que queda el mismo valor. Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 91 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 92. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Punteros (cont.) En esta versi´on en cambio, pasamos la direcci´on donde est´a x: 1 #include <iostream> 2 using namespace std; 3 4 void f(int* p) { 5 cout << "p = " << p << endl; 6 cout << "*p = " << *p << endl; 7 *p = 5; 8 cout << "p = " << p << endl; 9 } 10 11 int main() { 12 int x = 47; 13 cout << "x = " << x << endl; 14 cout << "&x = " << &x << endl; 15 f(&x); 16 cout << "x = " << x << endl; 17 } Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 92 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 93. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Punteros (cont.) Imprime: 1 [mstorti@galileo sources]$ ./try41.bin 2 x = 47 3 &x = 0x7ffcf3047dcc 4 p = 0x7ffcf3047dcc 5 *p = 47 6 p = 0x7ffcf3047dcc 7 x = 5 8 [mstorti@galileo sources]$ Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 93 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 94. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Referencias Los punteros son muy ´utiles pero engorrosos porque hay que estar dereferenciando al puntero cada vez. C++ introdujo las referencias que son completamente equivalentes a los punteros pero evitan la dereferenciaci´on. 1 #include <iostream> 2 using namespace std; 3 4 void f(int& r) { 5 cout << "r = " << r << endl; 6 cout << "&r = " << &r << endl; 7 r = 5; 8 cout << "r = " << r << endl; 9 } 10 11 int main() { 12 int x = 47; 13 cout << "x = " << x << endl; 14 cout << "&x = " << &x << endl; 15 f(x); // Looks like pass-by-value, 16 // is actually pass by reference 17 cout << "x = " << x << endl; 18 } Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 94 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 95. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Referencias (cont.) Imprime: 1 [mstorti@galileo sources]$ ./try42.bin 2 x = 47 3 &x = 0x7ffd244d1aac 4 r = 47 5 &r = 0x7ffd244d1aac 6 r = 5 7 x = 5 8 [mstorti@galileo sources]$ Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 95 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 96. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Punteros a void • El compilador s´olo acepta que asignemos a una variable de tipo int* la direcci´on de una variable de tipo int, en otro caso da un error 1 int *p; 2 int n; 3 p = &n; // OK 4 double a; 5 p = &a; // Error • El tipo void* permite almacenar un puntero a cualquier tipo de variable 1 void* vp; 2 char c; 3 int i; 4 float f; 5 double d; 6 vp = &c; 7 vp = &i; 8 vp = &f; 9 vp = &d; Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 96 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 97. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Punteros a void (cont.) • Una vez que una direcci´on es asignada a un void* el compilador no puede saber de que tipo es el objeto al cual apunta, y por lo tanto no se puede dereferenciar 1 int i = 99; 2 void* vp = &i; 3 *vp = 3; // Error de compilacion • Para poder recuperar el objeto tenemos que castear el puntero, de esa forma le estamos diciendo al compilador que es del tipo indicado 1 int i = 99; 2 void* vp = &i; 3 *((int*)vp) = 3; // OK! • Si casteamos al tipo incorrecto el compilador no protesta, pero se puede producir un error en tiempo de ejecuci´on 1 int i = 99; 2 void* vp = &i; 3 // Compila OK, posible error en tiempo de ejecuci´on 4 *((string*)vp) = "Hello world"; Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 97 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 98. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Scope de las variables Una variable existe desde su definici´on hasta la siguiente llave que cierra (}). Eso se llama el scope de la variable. 1 // How variables are scoped 2 int main() { 3 int scp1; 4 // scp1 visible here 5 { 6 // scp1 still visible here 7 //. . . . . 8 int scp2; 9 // scp2 visible here 10 //. . . . . 11 { 12 // scp1 & scp2 still visible here 13 //. . 14 int scp3; 15 // scp1, scp2 & scp3 visible here 16 // . . . 17 } // scp3 destroyed here 18 // scp3 not available here Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 98 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 99. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz 19 // scp1 & scp2 still visible here 20 // . . . 21 } // scp2 destroyed here 22 // scp3 & scp2 not available here 23 // scp1 still visible here 24 //. . 25 } // scp1 destroyed here Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 99 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 100. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Definiendo variables on-the-fly En C todas las variables deben ser definidas al comienzo del scope. En C++ se pueden definir en cualquier lugar. 1 // On-the-fly variable definitions 2 #include <iostream> 3 using namespace std; 4 5 int main() { 6 //. . 7 { // Begin a new scope 8 int q = 0; // C requires definitions here 9 //. . 10 // Define at point of use: 11 for(int i = 0; i < 100; i++) { 12 q++; // q comes from a larger scope 13 // Definition at the end of the scope: 14 int p = 12; 15 } 16 int p = 1; // A different p 17 } // End scope containing q & outer p 18 cout << "Type characters:" << endl; Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 100 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 101. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz 19 while(char c = cin.get() != ’q’) { 20 cout << c << " wasn’t it" << endl; 21 if(char x = c == ’a’ | | c == ’b’) 22 cout << "You typed a or b" << endl; 23 else 24 cout << "You typed " << x << endl; 25 } 26 cout << "Type A, B, or C" << endl; 27 switch(int i = cin.get()) { 28 case ’A’: cout << "Snap" << endl; break; 29 case ’B’: cout << "Crackle" << endl; break; 30 case ’C’: cout << "Pop" << endl; break; 31 default: cout << "Not A, B or C!" << endl; 32 } 33 } Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 101 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 102. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Definiendo variables on-the-fly (cont.) Las variables que est´an fuera de todas las funciones son globales, su scope es todo el programa, inclu´ıdo dentro de las funciones. 1 // == file1.cpp == 2 // Demonstration of global variables 3 #include <iostream> 4 using namespace std; 5 6 int globe; 7 void func(); 8 int main() { 9 globe = 12; 10 cout << globe << endl; 11 func(); // Modifies globe 12 cout << globe << endl; 13 } 14 // == file2.cpp == 15 // Accessing external global variables 16 extern int globe; 17 // (The linker resolves the reference) 18 void func() { Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 102 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 103. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz 19 globe = 47; 20 } Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 103 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 104. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Variables locales Las variables que existen dentro de un scope son locales, tambi´en se les llama autom´aticas ya que son creadas en el momento de llegar a ese bloque. La memoria que le es asignada no tiene porque ser siempre la misma, por lo tanto la variable no retiene el valor que le fue asignado antes. 1 void f(int x) { 2 int a; 3 cout << "a en f(): " << a << endl; 4 cout << "&a en f(): " << &a << endl; 5 a=x; 6 cout << "a en f() despues de asignar: " << a << endl; 7 } 8 9 void g(int x) { 10 int a; 11 cout << "a en g(): " << a << endl; 12 cout << "&a en g(): " << &a << endl; 13 a=x; 14 cout << "a en g() despues de asignar: " << a << endl; 15 } 16 17 void h(int x) { Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 104 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 105. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz 18 int a; 19 f(435); 20 cout << "a en h(): " << a << endl; 21 cout << "&a en h(): " << &a << endl; 22 a=x; 23 cout << "a en h() despues de asignar: " << a << endl; 24 } 25 26 int main() { 27 f(23); 28 g(45); 29 f(23); 30 g(45); 31 h(234); 32 return 0; 33 } Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 105 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 106. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Variables locales (cont.) El resultado es: 1 [mstorti@galileo garage]$$ ./try2.bin 2 a en f(): 0 3 &a en f(): 0x7fff6df56d1c 4 a en f() despues de asignar: 23 5 a en g(): 23 6 &a en g(): 0x7fff6df56d1c 7 a en g() despues de asignar: 45 8 a en f(): 45 9 &a en f(): 0x7fff6df56d1c 10 a en f() despues de asignar: 23 11 a en g(): 23 12 &a en g(): 0x7fff6df56d1c 13 a en g() despues de asignar: 45 14 a en f(): 59 15 &a en f(): 0x7fff6df56cdc 16 a en f() despues de asignar: 435 17 a en h(): 45 18 &a en h(): 0x7fff6df56d1c Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 106 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 107. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz 19 a en h() despues de asignar: 234 20 [mstorti@galileo garage]$$ Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 107 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 108. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Punteros a variables locales Si una variable sale de scope, es un error tratar de utilizar punteros que apuntaban a esa variable. 1 int *p; 2 for (int j=0; j<N; j++) { 3 int z; 4 p = &z; 5 . . . 6 } 7 // ERROR (z no existe mas) 8 cout << "contenido de *p " << *p << endl; Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 108 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 109. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Variables est´aticas Si queremos que el ´area asignada a una variable local sea siempre el mismo, entonces le agregamos el keyword static. Un ejemplo cl´asico es una funci´on que cuenta cuantas veces fue llamada: 1 void f() { 2 static int count=0; 3 cout << "f() fue llamada " << count << " veces" << endl; 4 cout++; 5 } 6 7 int main() { 8 for (int j=0; j<10; j++) 9 f(); 10 return 0; 11 } Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 109 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 110. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Variables est´aticas (cont.) El resultado es: 1 [mstorti@galileo garage]$ ./try14.bin 2 f() fue llamada 0 veces 3 f() fue llamada 1 veces 4 f() fue llamada 2 veces 5 f() fue llamada 3 veces 6 f() fue llamada 4 veces 7 f() fue llamada 5 veces 8 f() fue llamada 6 veces 9 f() fue llamada 7 veces 10 f() fue llamada 8 veces 11 f() fue llamada 9 veces 12 [mstorti@galileo garage]$ Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 110 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 111. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Constantes Si se utilizar´a muchas veces un valor que es constante se pueden hacer a trav´es de un macro 1 #define PI 3.141459 o bien a trav´es de una variable de tipo const 1 const double pi = 3.141459; Es m´as prolijo esto ´ultimo (le permite al compilador hacer chequeo de tipo). Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 111 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 112. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Operadores. Asignaci´on El caracter = se utiliza como el operador de asignaci´on: 1 A=4; Lo que est´a a la izquierda de = es el lvalue y lo que est´a a la derecha el rvalue. El rvalue puede ser cualquier expresi´on. El compilador la evalua y asigna el resultado a lo que est´a en el lvalue. Ahora bien lo que est´a en el lvalue no puede ser cualquier cosa, debe ser una variable o cualquier otra cosa a la cual se le pueda asignar un valor. Por ejemplo no puede ser una constante, es decir no podemos hacer 1 4=A; Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 112 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 113. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Operadores matem´aticos Los operadores matem´aticos binarios usuales son +-*/. Cada uno de ellos se puede usar en forma de acumulaci´on +=, -=, *=, /=. Por ejemplo 1 x += 5; es equivalente a 1 x = x + 5; Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 113 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 114. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Operadores relacionales Son 1 >, <, >=, <=, ==, != Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 114 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 115. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Operadores l´ogicos Son && (and) y || (or). Recordar que en C/C++ muchos tipos se castean autom´aticamente a bool, siendo 0 el valor falso y cualquier otro valor verdadero. Cuando se imprimen los valores booleanos dan 0 o 1. ! es la negaci´on. Son operadores cortocircuitados es decir si hacemos 1 expr1 && expr2 entonces primero se evalua expr1 y si da falso, entonces expr2 NO se eval´ua, ya que no es necesario porque la expresi´on l´ogica resultar´a en falso de todas formas. Eso puede ser importante, por ejemplo 1 if (n>0 && m/n!=3) . . . est´a garantizado que no dar´a error si n==0 ya que si es as´ı directamente la divisi´on por n no se har´a. Lo mismo ocurre en 1 expr1 | | expr2 si la primera da verdadero. Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 115 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 116. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz El operador hook Es una forma muy compacta de escribir un if-else. Por ejemplo esta expresi´on calcula el m´ınimo de dos valores 1 x = (m<n ? m : n); Se puede usar tambi´en en un lvalue. La siguiente expresi´on asigna al menor de m,n el valor 23. 1 (m<n ? m : n) = 23; Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 116 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 117. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Errores comunes con los operadores • Las reglas de precedencia a veces son simples, pero si se escriben expresiones complejas ya no. Ante la duda utilizar par´entesis. • No confundir = con ==. Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 117 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 118. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Operadores de cast • Si el compilador ve que estamos mezclando tipos en una asignaci´on, insertar´a una operaci´on de cast (conversi´on de tipo) autom´aticamente 1 int x=5; 2 double z=x; // OK 3 z=23.3; 4 x=z; // se pierde la mantisa (truncamiento) 5 x = (int) z; // cast explicito 6 x = int(z); // otra forma del cast explicito 7 8 int ixp = &x; // error, no puede convertir ptr a int 9 long int ixp2 = (long int)&x; // OK! 10 long int ixp3 = static-cast<long int>(&x); // OK! Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 118 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 119. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Operador sizeof • Retorna el tama˜no de una variable o tipo en bytes 1 cout << "sizeof(char) " << sizeof(char) << endl; // ->1 2 cout << "sizeof(int) " << sizeof(int) << endl; // ->4 3 cout << "sizeof(float) " << sizeof(float) << endl; // ->4 4 cout << "sizeof(double) " << sizeof(double) << endl; // ->8 5 6 double a; 7 cout << "sizeof(a) " << sizeof(a) << endl; // ->8 8 cout << "sizeof(&a) " << sizeof(&a) << endl; // ->8 (in x86-64) 9 int x; 10 cout << "sizeof(&x) " << sizeof(&x) << endl; // ->8 (in x86-64) Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 119 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 120. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz typedef: Aliases de tipos • Permite hacer un alias de un tipo a un nuevo tipo 1 typedef unsigned long int ulong; 2 . . . 3 ulong x; • Simple para tipos b´asicos, m´as complicado para punteros 1 typedef int *int-p; • La regla es que se escribe una l´ınea como la declaraci´on de una variable con typedef al principio y reemplazando la variable por el tipo. • Esto permite hacer expresiones m´as cortas pero adem´as tiene un uso muy importante. Permitir cambiar de tipo todas las variables de un programa 1 typedef float scalar; 2 scalar i,j,k; Para cambiar todo el programa a doble precisi´on: 1 typedef double scalar; Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 120 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 121. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Estructuras • Se pueden definir nuevos tipos agrupando varios miembros en una estructura. Los miembros de la estructura se toman con el operador .: 1 struct A { 2 char c; 3 int m; 4 float f; 5 double b; 6 }; 7 8 void printa(A a) { 9 cout << "structure is (" << a.c << "," << a.m << "," 10 << a.f << "," << a.b << ")" << endl; 11 } 12 . . . 13 14 A a1, a2; 15 a1.c = ’h’; 16 a2.m = 23; 17 printa(a1); Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 121 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 122. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Estructuras (cont.) Se pueden tomar punteros a estructuras y enlazarlas 1 struct cell { 2 char c; 3 double x; 4 cell *next; 5 }; 6 7 int main() { 8 cell c1,c2,c3; 9 c1.c = ’a’; c1.x = 1; c1.next = &c2; 10 c2.c = ’b’; c2.x = 2; c2.next = &c3; 11 c3.c = ’c’; c3.x = 3; c3.next = &c1; 12 13 cell *cp = &c1; 14 for (int k=0; k<20; k++) { 15 cout << "cp " << cp << ", c " 16 << (*cp).c << ", x " << (*cp).x << endl; 17 cp = (*cp).next; 18 } 19 } Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 122 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 123. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Estructuras (cont.) 1 cell c1,c2,c3; 2 c1.c = ’a’; c1.x = 1; c1.next = &c2; 3 c2.c = ’b’; c2.x = 2; c2.next = &c3; 4 c3.c = ’c’; c3.x = 3; c3.next = &c1; c='a' x=1 next c1 c='b' x=2 next c2 c='c' x=3 next c3 Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 123 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 124. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Estructuras (cont.) El resultado es 1 [mstorti@galileo garage]$$ ./try8.bin 2 cp 0x7fff571b2d20, c a, x 1 3 cp 0x7fff571b2d00, c b, x 2 4 cp 0x7fff571b2ce0, c c, x 3 5 cp 0x7fff571b2d20, c a, x 1 6 . . . 7 cp 0x7fff571b2d20, c a, x 1 8 cp 0x7fff571b2d00, c b, x 2 9 [mstorti@galileo garage]$$ Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 124 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 125. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Arrow operator Como en el ejemplo anterior es muy com´un la compinaci´on (*cp).x es decir tener un puntero a una estructura cp y querer tomar un miembro x de la estructura apuntada. Como es tan com´un hay un atajo sint´actico para eso 1 (*cp).x es equivalente a cp->x Entonces el lazo del programa anterior pasa a ser 1 for (int k=0; k<20; k++) { 2 cout << "cp " << cp << ", c " << cp->c 3 << ", x " << cp->x << endl; 4 cp = cp->next; 5 } Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 125 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 126. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Enum’s • Supongamos que queremos definir una estructura shape que contiene una forma geom´etrica, digamos las coordenadas x,y de su centro y un entero que indica su forma. Para ello incluimos un entero gtype (por geometric type) que define que tipo de forma es. Podemos por ejemplo asignar arbitrariamente gtype=0 para c´ırculos, 1=cuadrados, 2=rect´angulos. 1 struct shape { 2 double x,y; 3 int gtype; 4 }; Entonces una funci´on que imprime la forma ser´ıa algo as´ı como 1 void draw(shape s) { 2 if (s.gtype==0) //. . . imprime un circulo 3 else if (s.gtype==1) //. . . imprime un cuadrado 4 else if (s.gtype==2) //. . . imprime un rect 5 . . . 6 } El problema con esto es que tenemos que guardar mentalmente una tabla para saber que entero correspond´ıa a cada forma. Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 126 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 127. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Enum’s (cont.) Una posibilidad es usar macros 1 #define CIRCLE 0 2 #define SQUARE 1 3 #define RECTANGLE 2 4 5 void draw(shape s) { 6 if (s.gtype==CIRCLE) //. . . imprime un circulo 7 else if (s.gtype==SQUARE) //. . . imprime un cuadrado 8 else if (s.gtype==RECTANGLE) //. . . imprime un rect 9 . . . 10 } Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 127 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 128. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Enum’s (cont.) Pero, como ya dijimos, es preferible no usar macros, para esto est´a el enum: 1 enum GeoType { circle, square, rectangle}; 2 3 struct shape { 4 double x,y; 5 GeoType gtype; 6 }; 7 8 void draw(shape s) { 9 if (s.gtype==circle) //. . . imprime un circulo 10 else if (s.gtype==square) //. . . imprime un cuadrado 11 else if (s.gtype==rectangle) //. . . imprime un rect 12 . . . 13 } • Internamente los enums son enteros, pero esto es transparente para nosotros. • El compilador traduce cada identificador de la lista a un entero consecutivo. • Se puede forzar a que tomen un valor espec´ıfico 1 enum GeoType { circle=5, square=10, rectangle=15}; Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 128 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 129. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Arreglos de estructuras • Vimos que podemos definir arreglos como int v[100]. • Tambi´en lo podemos hacer con estructuras cell cellv[100] • Los elementos son guardados en forma consecutiva 1 struct cell { 2 double x; 3 cell *next; 4 }; 5 6 for (int j=0; j<4; j++) 7 cout << "&cellv[" << j << "] " 8 << (long int)&cellv[j] << endl; 9 . . . 10 &cellv[0] 140736201505632 11 &cellv[1] 140736201505648 12 &cellv[2] 140736201505664 ya que el tama˜no de la celda es de 16 bytes (8 para el doble y 8 para el puntero): 1 cout << "sizeof(cell): " << sizeof(cell) << endl; 2 . . . 3 sizeof(cell): 16 Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 129 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 130. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Punteros y arreglos Si imprimimos un arreglo, el compilador lo imprime como hexadecimal, o sea como si fuera un puntero 1 int v[100]; 2 cout << v << endl; 3 . . . 4 -> 0x7fff7e388420 Esto es porque el compilador s´olo almacena para el vector la direcci´on donde comienza el ´area asignada al vector. Esto lo podemos verificar imprimiento la direcci´on del primer elemento 1 cout << &cellv[0] << endl; 2 -> 0x7fff7e388420 Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 130 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 131. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Punteros y arreglos (cont.) Si tomamos un puntero al primer elemento podemos manipular al vector a trav´es de ese puntero 1 int v[100]; 2 int *p= &v[0]; 3 for (int j=0; j<100, j++) *(p+j) = 100*j; De hecho en la mayor´ıa de los casos punteros y arreglos son intercambiables, por ejemplo a los punteros se les puede aplicar el operador [] de manera que se lo puede utilizar como un vector. 1 int v[100]; 2 int *p= &v[0]; 3 for (int j=0; j<1000, j++) p[j] = 100*j; Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 131 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 132. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Arreglos de punteros • Tambi´en se pueden tener arreglos de punteros 1 int *v[100]; // arreglo de 100 punteros a enteros • Los arreglos de caracteres, son de tipo char* entonces si queremos tener un arreglo de “strings de C”, tenemos un arreglo de arreglos de char, o lo que es equivalente a arreglos de punteros a char 1 char *as[ ]; 2 char **as; // equivalente Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 132 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 133. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Arreglos de punteros (cont.) • Un caso frecuente de esto es la segunda forma de llamada a main(). Si llamamos a nuestro programa con argumentos 1 int main(int argc,char **argv) { 2 for (int j=0; j<argc; j++) 3 cout << j << ": " << argv[j] << endl; 4 return 0; 5 } El resultado es 1 $$ ./try10.bin -u mstorti -d 453 -l 34 -f 34.56 2 0: ./try10.bin 3 1: -u 4 2: mstorti 5 3: -d 6 4: 453 7 5: -l 8 6: 34 9 7: -f 10 8: 34.56 El shell (en este caso bash) divide los argumentos pasados en la l´ınea de comando por whitespace y construye un arreglo de strings Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 133 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 134. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Arreglos de punteros (cont.) • El acceso a elementos de un arreglo de C es extremadamente r´apido. • Sin embargo si se accede a posiciones m´as all´a de la ´ultima posici´on del vector se puede producir un error 1 int v[100]; 2 . . . 3 v[100] = x; // Muy probablemente SIGSEGV o SEGFAULT • Se debe conocer el tama˜no del vector en tiempo de compilaci´on (hay una forma de hacerlo din´amico, con new[]/delete[] o malloc()/free(). • La clase vector<> es mucho m´as vers´atil y m´as segura. Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 134 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 135. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Arreglos de punteros (cont.) Podemos verificar que los elementos de un vector est´an en posiciones contiguas. 1 int a[10]; 2 cout << "sizeof(int) = "<< sizeof(int) << endl; 3 for(int i = 0; i < 10; i++) 4 cout << "&a[" << i << "] = " 5 << (long)&a[i] << endl; produce 1 $$ ./try17.bin 2 sizeof(int) = 4 3 &a[0] = 140736359816368 4 &a[1] = 140736359816372 5 &a[2] = 140736359816376 6 &a[3] = 140736359816380 Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 135 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 136. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Aritm´etica de punteros Se pueden hacer cuentas con punteros de tipo ptr = ptr + int y todas las derivadas, por ejemplo 1 ptr = ptr + int 2 int = ptr - ptr 3 ptr += int 4 ptr++ 5 ptr-- En todas estas operaciones el entero indica posiciones en el vector, no bytes. Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 136 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 137. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Aritm´etica de punteros (cont.) 1 int i[10]; 2 double d[10]; 3 int* ip = i; 4 double* dp = d; 5 cout << "ip = " << (long)ip << endl; 6 ip++; 7 cout << "ip = " << (long)ip << endl; 8 cout << "dp = " << (long)dp << endl; 9 dp++; 10 cout << "dp = " << (long)dp << endl; produce 1 [mstorti@galileo garage]$$ ./try18.bin 2 ip = 140733418503296 3 ip = 140733418503300 4 dp = 140733418503216 5 dp = 140733418503224 Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 137 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 138. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Tama˜nos de estructuras Cuando se usan estructuras con tipos mezclados puede ser que el tama˜no del tipo combinado no sea igual a la suma de los tama˜nos de los tipos (pero seguro es mayor o igual) porque el compilador tiene que alinear los tipos. 1 struct A { 2 char c; 3 double d; 4 }; da sizeof(A) -> 16, y 1 struct B { char c; double d; char c2; }; 2 struct C { char c; char c2; double d; }; da 1 sizeof(B) -> 24 2 sizeof(C) -> 16 Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 138 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 139. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Programaci´on Orientada a Objetos Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 139 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 140. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Abstracci´on de datos Un contenedor de elementos de longitud arbitraria 1 #ifndef CSTASH-H 2 #define CSTASH-H 3 4 struct CStash { 5 int size; // Size of each space 6 int quantity; // Number of storage spaces 7 int next; // Next empty space 8 // Dynamically allocated array of bytes: 9 unsigned char* storage; 10 }; 11 12 void initialize(CStash* s, int size); 13 void cleanup(CStash* s); 14 int add(CStash* s, const void* element); 15 void* fetch(CStash* s, int index); 16 int count(CStash* s); 17 void inflate(CStash* s, int increase); 18 19 #endif Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 140 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 141. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Abstracci´on de datos (cont.) 1 struct CStash { 2 int size; // Size of each space 3 int quantity; // Number of storage spaces 4 int next; // Next empty space 5 // Dynamically allocated array of bytes: 6 unsigned char* storage; 7 }; store quantity next size used free Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 141 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 142. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Abstracci´on de datos (cont.) 1 // Implementation of example C-like library 2 // Declare structure and functions: 3 #include "./cstash.h" 4 #include <iostream> 5 #include <cassert> 6 7 using namespace std; 8 // Quantity of elements to add 9 // when increasing storage: 10 const int increment = 100; 11 12 void initialize(CStash* s, int sz) { 13 s->size = sz; 14 s->quantity = 0; 15 s->storage = 0; 16 s->next = 0; 17 } 18 19 int add(CStash* s, const void* element) { 20 if(s->next >= s->quantity) //Enough space left? 21 inflate(s, increment); 22 // Copy element into storage, Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 142 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 143. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz 23 // starting at next empty space: 24 int startBytes = s->next * s->size; 25 unsigned char* e = (unsigned char*)element; 26 for(int i = 0; i < s->size; i++) 27 s->storage[startBytes + i] = e[i]; 28 s->next++; 29 return(s->next - 1); // Index number 30 } 31 32 void* fetch(CStash* s, int index) { 33 // Check index boundaries: 34 assert(0 <= index); 35 if(index >= s->next) 36 return 0; // To indicate the end 37 // Produce pointer to desired element: 38 return &(s->storage[index * s->size]); 39 } 40 41 int count(CStash* s) { 42 return s->next; // Elements in CStash 43 } 44 45 void inflate(CStash* s, int increase) { 46 assert(increase > 0); 47 int newQuantity = s->quantity + increase; Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 143 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 144. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz 48 int newBytes = newQuantity * s->size; 49 int oldBytes = s->quantity * s->size; 50 unsigned char* b = new unsigned char[newBytes]; 51 for(int i = 0; i < oldBytes; i++) 52 b[i] = s->storage[i]; // Copy old to new 53 delete [ ](s->storage); // Old storage 54 s->storage = b; // Point to new memory 55 s->quantity = newQuantity; 56 } 57 58 void cleanup(CStash* s) { 59 if(s->storage != 0) { 60 cout << "freeing storage" << endl; 61 delete [ ]s->storage; 62 } 63 } Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 144 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 145. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Abstracci´on de datos (cont.) • CStash es un tipo que permite almacenar una cantidad ilimitada de elementos de tama˜no size. • Tiene un ´area de almacenamiento interno unsigned char *storage. • Se pueden agregar elementos con add(), si el tama˜no del almacenamiento interno no es suficiente entences se incrementa en una dada cantidad (por default 100). • initialize() realiza la inicializacion de la estructura, poniendo a cero los diferentes contadores y el tama˜no de los elementos al valor entrado por el usuario (int sz). • add() agrega un elemento copi´andolo byte por byte a storage. Si el tama˜no no es suficiente llama a inflate() para alocar una nueva ´area recopiando todo el ´area previa y agregando el nuevo elemento. • quantity es el n´umero de lugares disponibles next es la cantidad de lugares realmente ocupados. • fetch() retorna el puntero al lugar donde comienza el elemento en la posici´on index. Primero chequea que efectivamente el ´ındice est´e en el rango de valores apropiados (0<=index<next). En caso contrario retorna un puntero nulo. Est´a garantizado que el puntero nulo no apunta a ning´un Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 145 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 146. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz lado de la memoria. • count() retorna la cantidad de elementos que hay en el contenedor. Simplemente retorna next. • Alocaci´on din´amica de memoria: Como no sabemos en principio que tama˜no va a tomar el ´area de memoria vamos alocando din´amicamente con el operador new 1 new unsigned char[newBytes]; • En general se puede hacer 1 t = new Type; // aloca un solo objeto 2 tp = new Type[count]; // aloca un arreglo de count objetos • El ´area utilizada debe ser liberada. Si no (y si la alocaci´on se hace repetidamente) se produce un memory leak. 1 delete t; 2 delete[ ] tp; • Las ´areas de memoria reservadas con new se alocan en el heap. Si el heap se acaba la alocaci´on da un error (OJO que no necesariamente retorna un puntero nulo). • Los pedazos de memoria alocados con new pueden crear fragmentaci´on de la memoria. (No hay un defragmentador). Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 146 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 147. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Abstracci´on de datos (cont.) 1 #include "./cstash.h" 2 #include <fstream> 3 #include <iostream> 4 #include <string> 5 #include <cassert> 6 using namespace std; 7 8 int main() { 9 // Define variables at the beginning 10 // of the block, as in C: 11 CStash intStash, stringStash; 12 int i; 13 char* cp; 14 ifstream in; 15 string line; 16 const int bufsize = 80; 17 // Now remember to initialize the variables: 18 initialize(&intStash, sizeof(int)); 19 for(i = 0; i < 100; i++) 20 add(&intStash, &i); 21 for(i = 0; i < count(&intStash); i++) Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 147 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 148. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz 22 cout << "fetch(&intStash, " << i << ") = " 23 << *(int*)fetch(&intStash, i) 24 << endl; 25 // Holds 80-character strings: 26 initialize(&stringStash, sizeof(char)*bufsize); 27 in.open("./trycstash.cpp"); 28 assert(in); 29 while(getline(in, line)) 30 add(&stringStash, line.c-str()); 31 i = 0; 32 while((cp = (char*)fetch(&stringStash,i++))!=0) 33 cout << "fetch(&stringStash, " << i << ") = " 34 << cp << endl; 35 cleanup(&intStash); 36 cleanup(&stringStash); 37 return 0; 38 } Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 148 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 149. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Abstracci´on de datos (cont.) Resultado: 1 [mstorti@galileo garage]$ ./trycstash.bin 2 fetch(&intStash, 0) = 0 3 fetch(&intStash, 1) = 1 4 fetch(&intStash, 2) = 2 5 fetch(&intStash, 3) = 3 6 . . . 7 fetch(&intStash, 97) = 97 8 fetch(&intStash, 98) = 98 9 fetch(&intStash, 99) = 99 10 0: #include "./cstash.h" 11 1: #include <fstream> 12 2: #include <iostream> 13 3: #include <string> 14 . . . 15 37: cleanup(&stringStash); 16 38: return 0; 17 39: } 18 freeing storage 19 freeing storage 20 [mstorti@galileo garage]$ Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 149 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 150. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz POO b´asica La librer´ıa que creamos tiene dos problemas b´asicos: • Ser´ıa bueno que la construcci´on y destrucci´on de los objetos fuera autom´atica. • Poluci´on del espacio de nombres: Si necesitamos otro contenedor no vamos a poder usar los nombres initialize() y cleanup(). Una posible soluci´on ser´ıa usar nombres con prefijos CStash_initialize(), CStash_cleanup() ... Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 150 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 151. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz POO b´asica (cont.) 1 struct Stash { 2 int size; // Size of each space 3 int quantity; // Number of storage spaces 4 int next; // Next empty space 5 // Dynamically allocated array of bytes: 6 unsigned char* storage; 7 // Functions! 8 void initialize(int size); 9 void cleanup(); 10 int add(const void* element); 11 void* fetch(int index); 12 int count(); 13 void inflate(int increase); 14 }; Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 151 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 152. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz POO b´asica (cont.) • Ahora las funciones aparecen dentro de la estructura, de manera que esta act´ua como un namespace, de manera que la funciones se llaman ahora Stash::initialize(), Stash::cleanup() • No hace falta pasar a las funciones el puntero al objeto. Esto se hace autom´aticamente llamando a la funci´on como miembro de un objeto 1 Stash s1,s2,s3; 2 s1.initialize(10); Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 152 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 153. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz POO b´asica (cont.) 1 // C library converted to C++ 2 // Declare structure and functions: 3 #include "CppLib.h" 4 #include <iostream> 5 #include <cassert> 6 using namespace std; 7 // Quantity of elements to add 8 // when increasing storage: 9 const int increment = 100; 10 11 void Stash::initialize(int sz) { 12 size = sz; 13 quantity = 0; 14 storage = 0; 15 next = 0; 16 } 17 18 int Stash::add(const void* element) { 19 if(next >= quantity) // Enough space left? 20 inflate(increment); 21 // Copy element into storage, 22 // starting at next empty space: Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 153 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 154. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz 23 int startBytes = next * size; 24 unsigned char* e = (unsigned char*)element; 25 for(int i = 0; i < size; i++) 26 storage[startBytes + i] = e[i]; 27 next++; 28 return(next - 1); // Index number 29 } 30 31 void* Stash::fetch(int index) { 32 // Check index boundaries: 33 assert(0 <= index); 34 if(index >= next) 35 return 0; // To indicate the end 36 // Produce pointer to desired element: 37 return &(storage[index * size]); 38 } 39 40 int Stash::count() { 41 return next; // Number of elements in CStash 42 } 43 44 void Stash::inflate(int increase) { 45 assert(increase > 0); 46 int newQuantity = quantity + increase; 47 int newBytes = newQuantity * size; Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 154 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 155. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz 48 int oldBytes = quantity * size; 49 unsigned char* b = new unsigned char[newBytes]; 50 for(int i = 0; i < oldBytes; i++) 51 b[i] = storage[i]; // Copy old to new 52 delete [ ]storage; // Old storage 53 storage = b; // Point to new memory 54 quantity = newQuantity; 55 } 56 57 void Stash::cleanup() { 58 if(storage != 0) { 59 cout << "freeing storage" << endl; 60 delete [ ]storage; 61 } 62 } Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 155 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 156. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz POO b´asica (cont.) • Adentro de las funciones miembro no es necesario dereferenciar al objeto para obtener los miembros size, quantity. Es decir en vez de aparecer s->size ahora s´olo aparece size, lo que ocurre es que al llamar s1.initialize() la variable size corresponde al del objeto s1. • Si uno necesita conocer el puntero a la estructura en la que estoy en este momento se usa el keyword this que es un puntero al objeto en el que estamos parados 1 void Stash::initialize(int sz) { 2 cout << "this: " << this << endl; 3 . . . 4 } 5 6 Stash s1; 7 cout << "&s1: " << &s1 << endl; 8 s1.initialize(); Imprimen el mismo puntero. Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 156 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 157. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz POO b´asica (cont.) 1 // Test of C++ library 2 #include "CppLib.h" 3 #include ". ./require.h" 4 #include <fstream> 5 #include <iostream> 6 #include <string> 7 using namespace std; 8 9 int main() { 10 Stash intStash; 11 intStash.initialize(sizeof(int)); 12 for(int i = 0; i < 100; i++) 13 intStash.add(&i); 14 for(int j = 0; j < intStash.count(); j++) 15 cout << "intStash.fetch(" << j << ") = " 16 << *(int*)intStash.fetch(j) 17 << endl; 18 // Holds 80-character strings: 19 Stash stringStash; 20 const int bufsize = 80; 21 stringStash.initialize(sizeof(char) * bufsize); Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 157 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 158. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz 22 ifstream in("CppLibTest.cpp"); 23 assure(in, "CppLibTest.cpp"); 24 string line; 25 while(getline(in, line)) 26 stringStash.add(line.c-str()); 27 int k = 0; 28 char* cp; 29 while((cp =(char*)stringStash.fetch(k++)) != 0) 30 cout << "stringStash.fetch(" << k << ") = " 31 << cp << endl; 32 intStash.cleanup(); 33 stringStash.cleanup(); 34 } Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 158 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 159. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz POO b´asica (cont.) • Las llamadas a funciones de la librer´ıa se convierten as´ı 1 CStash-initialize(&s1,sz); 2 s1.initialize(size); Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 159 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 160. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Inclusion de headers • Algunos headers pueden incluir a otros, por ejemplo el header de una librer´ıa lib1.h puede incluir iostream. Entonces si otra librer´ıa lib2.h tambi´en incluye iostream, al querer incluir a las dos librer´ıas 1 #include <lib1.h> 2 #include <lib2.h> // Incluye iostream 2 veces -> error • No hay problema con las funciones, pero si con las estructuras (y clases). • Se utiliza un mecanismo con macros para evitar la doble inclusi´on. Podemos usar los macros para incluir condicionalmente partes del c´odigo. 1 #define FLAG 2 3 #ifdef FLAG 4 //. . . 5 #else 6 //. . . 7 #endif Notar que es muy diferente este condicional del preprocesador que el if-else de C++. En el del preprocesador s´olo uno de los bloques se compila. Quiere decir que se puede usar para usar diferentes pedazos de Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 160 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 161. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz c´odigo que de otra forma no compilar´ıa. Por ejemplo 1 #ifdef HAS-PETSC 2 //. . . Version que usa la libreria PETSC 3 #else 4 //. . . Version alternativa 5 #endif • El macro se puede definir usando un #define FLAG como arriba, o tambi´en al compilar usando $$ g++ -DFLAG ... • Lo contrario de definir un macro es hacerlo indefinido con #undef FLAG, a partir de ahi #ifdef FLAG da falso. • #undef se puede usar para redefinir macros 1 #define MAX-SIZE 100 2 . . . . 3 #define MAX-SIZE 1000 // -> Error 1 #define MAX-SIZE 100 2 3 . . . 4 #undef MAX-SIZE 5 #define MAX-SIZE 1000 // OK! Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 161 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 162. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Inclusion de headers (cont.) • Para evitar la doble inclusi´on se utiliza un macro de protecci´on 1 #ifndef STASH-H 2 #define STASH-H 3 // Type declaration here. . . 4 #endif // STASH-H • Ahora si se incluye dos veces el header no hay problema, ya que la segunda vez en realidad no es incluido. 1 #include <stash.h> 2 #include <stash.h> // no es incluido esta vez!! • El macro centinela STASH_H debe ser ´unico para ese archivo. Si otro archivo usa el mismo macro centinela entonces sus declaraciones no son incluidas 1 #include <libreria1/stash.h> 2 #include <libreria2/stash.h> // Error: este no es incluido Deberian usar LIBRERIA1_STASH_H y LIBRERIA2_STASH_H. Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 162 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 163. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Inclusion de headers (cont.) • Si en un header mylib.h se utilizan elementos de iostream es tentador poner un using namespace std; en el header, para no tener que andar poniendo el namespace std expl´ıcitamente (e.g. std::cout). • Lamentablemente esto producir´ıa que si un usuario incluye mylib.h todo su c´odigo pierde la protecci´on del namespace y volvemos a la situaci´on que quer´ıamos impedir con los namespace: la colisi´on de nombres. • Por lo tanto la regla es: NO usar using namespace.. en los headers, s´olo en los .cpp Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 163 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 164. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Estructuras enlazadas • La siguiente estructura Stack representa una pila implementada con celdas enlazadas. Las celdas son de otra estructura llamada Link que contiene el dato data y un puntero a la siguiente celda next. 1 struct Link { 2 void* data; 3 Link* next; 4 void initialize(void* dat, Link* nxt); 5 }; Stack S nextdata head nextdata nextdata nextdata Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 164 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 165. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Estructuras enlazadas (cont.) 1 struct Link { 2 void* data; 3 Link* next; 4 void initialize(void* dat, Link* nxt); 5 }; 6 7 struct Stack { 8 Link *head; 9 void initialize(); 10 void push(void* dat); 11 void* peek(); 12 void* pop(); 13 void cleanup(); 14 }; Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 165 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 166. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Estructuras enlazadas (cont.) • La funci´on push() mete un nuevo elemento en la pila, peek() retorna un puntero al elemento en el tope de la pila. pop() elimina un elemento del tope. initialize() y cleanup() son como antes: se encargan de la inicializaci´on y destrucci´on de la estructura. • El tipo de las celdas Link s´olo se usar´a con la clase Stack. Si nuestra librer´ıa quiere adem´as definir un tipo Queue que representa una cola, con celdas enlazadas, entonces no podr´a usar el mismo nombre Link para sus celdas. • Para evitar esta colisi´on ponemos la clase Link adentro de la clase Stack 1 struct Stack { 2 struct Link { 3 void* data; 4 Link* next; 5 void initialize(void* dat, Link* nxt); 6 } *head; 7 void initialize(); 8 void push(void* dat); 9 void* peek(); 10 void* pop(); Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 166 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 167. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz 11 void cleanup(); 12 }; • Notar que al definir el tipo Link en la misma declaraci´on del tipo se define un puntero Link *head a la primera celda. Por supuesto se puede hacer por separado tambi´en 1 struct Link { 2 . . . 3 }; 4 Link *head; Por eso las definiciones de estructuras struct Type {...}; terminan en un punto y coma, ya que all´ı se pueden definir objetos de tipo Type al mismo tiempo que se define el nuevo tipo. • Notar que cada estructura Stack y Link tienen su funci´on de inicializaci´on initialize(). • Link no tiene cleanup(), el mismo usario es responsable de liberar el espacio apuntado por data, si existe. Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 167 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 168. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Estructuras enlazadas (cont.) 1 // Linked list with nesting 2 #include "Stack.h" 3 #include ". ./require.h" 4 using namespace std; 5 6 void 7 Stack::Link::initialize(void* dat, Link* nxt) { 8 data = dat; 9 next = nxt; 10 } 11 12 void Stack::initialize() { head = 0; } 13 14 void Stack::push(void* dat) { 15 Link* newLink = new Link; 16 newLink->initialize(dat, head); 17 head = newLink; 18 } 19 20 void* Stack::peek() { 21 require(head != 0, "Stack empty"); 22 return head->data; 23 } Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 168 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 169. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz 24 25 void* Stack::pop() { 26 if(head == 0) return 0; 27 void* result = head->data; 28 Link* oldHead = head; 29 head = head->next; 30 delete oldHead; 31 return result; 32 } 33 34 void Stack::cleanup() { 35 require(head == 0, "Stack not empty"); 36 } Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 169 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 170. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Estructuras enlazadas (cont.) Uso de Stack 1 // Test of nested linked list 2 #include "Stack.h" 3 #include ". ./require.h" 4 #include <fstream> 5 #include <iostream> 6 #include <string> 7 using namespace std; 8 9 int main(int argc, char* argv[ ]) { 10 requireArgs(argc, 1); // File name is argument 11 ifstream in(argv[1]); 12 assure(in, argv[1]); 13 Stack textlines; 14 textlines.initialize(); 15 string line; 16 // Read file and store lines in the Stack: 17 while(getline(in, line)) 18 textlines.push(new string(line)); 19 // Pop the lines from the Stack and print them: 20 string* s; Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 170 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 171. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz 21 while((s = (string*)textlines.pop()) != 0) { 22 cout << *s << endl; 23 delete s; 24 } 25 textlines.cleanup(); 26 } Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 171 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 172. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz M´as sobre scoping Si existen varias versiones de variables con un mismo nombre, la que se ve es la del scope mas interno. Se puede acceder a las otras utilizando el operador de scope apropiado. Para las globales hay que usar el scop :: (sin nada a la izquierda). 1 // Global scope resolution 2 int a; 3 void f() {} 4 5 struct S { 6 int a; 7 void f(); 8 }; 9 10 void S::f() { 11 ::f(); // Would be recursive otherwise! 12 ::a++; // Select the global a 13 a--; // The a at struct scope 14 } 15 int main() { S s; f(); } Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 172 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 173. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Tipos Abstractos de Datos (ADT) Con este ejemplo hemos visto una idea fundamental de C++ que es incluir funciones adentro de las estructuras. Este nuevo tipo de estructura es llamado un Tipo Abstracto de Datos (Abstract Data Type, ADT)). Las variables de estos tipos se llaman objetos. Llamar una funci´on de la estructura sobre un objeto es mandarle un mensaje al objeto. Si bien encapsular datos y funciones en un TAD es un beneficio considerable para organizar el c´odigo y prevenir la colisi´on de nombres, la OOP (Programaci´on Orientada a Objetos) es mucho m´as que esto. Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 173 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 174. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Ocultando la implementaci´on Una librer´ıa t´ıpica de C consiste de una o m´as definiciones de estructuras (struct) y funciones asociadas que act´uan sobre dichas estructuras. En C++ las funciones se pueden asociar expl´ıcitamente a esas estructuras poniendo sus declaraciones dentro del scope de la estructura. Pero hay una cuesti´on adicional que es hasta donde el programador debe permitir que el usuario de la librer´ıa manipule a la estructura. Si el usuario lee las definiciones de la estructura puede por s´ı mismo manipular la estructura. Ahora bien, si en alg´un momento el programador cambia la forma en que est´a armada la estructura el c´odigo del usuario dejar´a de funcionar (“breaks the code”). Por ejemplo en la estructura Stack definida previamente el programador podr´ıa en el futuro decidir que es mejor alocar la memoria de a grandes chunks de 100 elementos o m´as que alocar de a uno como est´a hecho en esa implementaci´on. Si el c´odigo del usuario depende de que la alocaci´on se haga de a un elemento, entonces al producirse el cambio de implementaci´on su c´odigo dejar´a de funcionar. Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 174 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 175. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Ocultando la implementaci´on (cont.) En C esto se puede resolver parcialmente si el programador especifica en la documentaci´on de la librer´ıa las funciones con las cuales el usuario de la estructura debe manipular los objetos a trav´es de las funciones provistas, y hasta que punto puede usar directamente los datos almacenados en la estructura. Pero esto es s´olo un pacto entre el usuario y el programador, el compilador no tiene forma de conocer estas reglas y prevenir al usuario de manipular los objetos indebidamente. Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 175 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 176. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Control de acceso a los miembros El acceso a los miembros de una estructura en C++ se hace a trav´es de 3 especificadores de acceso public, private y protected. El keyword public quiere decir que todos los miembros siguientes son accesibles para cualquiera, como ocurre con los miembros de una struct por defecto. Por lo tanto, en el caso de una struct da lo mismo poner public al principio o no. Las dos declaraciones siguientes son por lo tanto equivalentes 1 struct A { 2 int i,j; 3 float f; 4 void func(); 5 }; 6 7 struct A { 8 public: 9 int i,j; 10 float f; 11 void func(); 12 }; Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 176 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 177. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Control de acceso a los miembros (cont.) La clave keyword private por el contrario, indica que los miembros correspondientes s´olo se pueden acceder desde c´odigo (es decir funciones) de la misma clase. 1 struct B { 2 private: 3 char j; 4 float f; 5 public: 6 int i; 7 void func(); 8 }; 9 10 void B::func() { 11 i = 0; 12 j = ’0’; // OK, access from a B function member 13 f = 0.0; // OK, idem 14 }; 15 16 int main() { 17 B b; 18 b.i = 1; // OK, public Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 177 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 178. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz 19 b.func(); // OK, public 20 b.j = ’1’; // Illegal, private 21 b.f = 1.0; // Illegal, private 22 } Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 178 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 179. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Control de acceso a los miembros (cont.) • B::func() puede acceder a los miembros privados, porque es una funcion de la clase, independientemente de si func() es a su vez privada o publica. • Una vez que se incluye el keyword private todas las declaraciones de miembros dato y funciones son privadas, hasta la siguiente keyword public. • Se pueden incluir tantas declaraciones private y public como sea necesario. • Se pueden incluir dos declaraciones private o public seguidas. • protected es una mezcla de los dos, pero ser´a explicado m´as adelante cuando se explique el concepto de herencia. Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 179 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 180. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Amistad (Friendship) El keyword friend permite declarar que una funci´on que no es miembro de la estructura tenga acceso a todos los miembros de la misma. 1 // Declaration (incomplete type specification): 2 struct X; 3 4 struct Y { 5 void f(X*); 6 }; 7 8 struct X { // Definition 9 private: 10 int i; 11 public: 12 void initialize(); 13 friend void g(X*, int); // Global friend 14 friend void Y::f(X*); // Struct member friend 15 friend struct Z; // Entire struct is a friend 16 friend void h(); 17 }; 18 19 void X::initialize() { Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 180 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 181. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz 20 i = 0; 21 } 22 23 void g(X* x, int i) { 24 x->i = i; 25 } 26 27 void Y::f(X* x) { 28 x->i = 47; 29 } 30 31 struct Z { 32 private: 33 int j; 34 public: 35 void initialize(); 36 void g(X* x); 37 }; 38 39 void Z::initialize() { 40 j = 99; 41 } 42 43 void Z::g(X* x) { 44 x->i += j; 45 } Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 181 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 182. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz 46 47 void h() { 48 X x; 49 x.i = 100; // Direct data manipulation 50 } 51 52 int main() { 53 X x; 54 Z z; 55 z.g(&x); 56 } Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 182 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 183. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Anidamiento (nesting) y amistad El est´andar dice que en principio una clases anidada no tienen que ser necesariamente amiga de la clase externa. 1 struct E { 2 private: 3 int x; 4 struct B { }; 5 struct I { 6 private: 7 B b; // error1: E::B is private 8 int y; 9 void f(E* p, int i) { 10 p->x = i; // error2: E::x is private 11 } 12 }; 13 int g(I* p) { return p->y; } // error3: I::y is private 14 }; Sin embargo en la pr´actica el GCC da acceso a la clase externa a la clase interna, pero no al rev´es. Es decir da error en 1 y 2, pero no en 3. Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 183 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 184. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Object layout Una de las condiciones de dise˜no de C++ fue que c´odigo v´alido en C deber´ıa compilar sin problemas en C++. Por esto las construcciones de tipo struct tienen a todos sus miembros p´ublicos. Cuando el compilador organiza los datos dentro del objeto los guarda en memoria en forma contigua, en el orden en el que est´an en la estructura. Cuando introducimos especificadores de acceso, cada bloque de acceso guarda sus miembros en forma contigua, pero los bloques de acceso pueden estar entre s´ı puestos de cualquier forma (como si cada uno fuera una estructura). Las cuestiones de privilegios de acceso (acceso a los miembros privados y p´ublicos de la clase) tiene sentido s´olo en el momento de compilaci´on. Una vez que el c´odigo fuente es convertido a c´odigo de m´aquina dos estructuras que difieren s´olo en cuanto a sus secciones private y public son indistinguibles entre s´ı, a menos del efecto discutido previamente de la disposici´on en la memoria (object layout). Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 184 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 185. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Clases Controlar el acceso a los miembros de una estructura es parte de lo que se llama “ocultar la implementaci´on” (implementation hiding). Esto es un concepto clave en OOP. En OOP se trata de ocultar lo m´as posible los miembros de la estructura, por eso lo deseable ser´ıa que todos los miembros fueran privados por defecto. Por eso en C++ existe un tipo de estructura alternativo class que es completamente equivalente a las struct de C, pero donde todos los miembros son por defecto private. Todas estas clases son equivalentes 1 class A { 2 int i,j,k; 3 public: 4 double z; 5 void f(); 6 }; 7 8 struct B { 9 private: 10 int i,j,k; Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 185 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 186. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz 11 public: 12 double z; 13 void f(); 14 }; 15 16 struct C { 17 double z; // salvo por el object layout 18 void f(); 19 private: 20 int i,j,k; 21 }; Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 186 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 187. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Clases (cont.) Vemos la clase Stash ahora con control de acceso. Todos los datos son privados. La funci´on inflate() tambi´en ya que s´olo es usada internamente. 1 class Stash { 2 int size; // Size of each space 3 int quantity; // Number of storage spaces 4 int next; // Next empty space 5 // Dynamically allocated array of bytes: 6 unsigned char* storage; 7 void inflate(int increase); 8 public: 9 void initialize(int size); 10 void cleanup(); 11 int add(void* element); 12 void* fetch(int index); 13 int count(); 14 }; Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 187 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 188. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Clases (cont.) En Stack ahora hacemos que toda la estructura Link sea privada o sea s´olo es accesible desde las funciones miembro de Stack. 1 class Stack { 2 struct Link { 3 void* data; 4 Link* next; 5 void initialize(void* dat, Link* nxt); 6 }* head; 7 public: 8 void initialize(); 9 void push(void* dat); 10 void* peek(); 11 void* pop(); 12 void cleanup(); 13 }; Notar que Link sigue siendo declarada como struct. De todas formas toda la estructura es privada, o sea que desde fuera de Stack no se puede acceder. Podr´ıamos tambi´en declararla como clase, pero entonces deber´ıamos declarar friend a Stack. Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 188 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 189. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Ocultando totalmente la implementaci´on Todav´ıa uno podr´ıa preguntarse si se puede ocultar a´un m´as la implementaci´on. Que el usuario vea s´olo la parte p´ublica. Otra raz´on es evitar la recompilaci´on innecesaria. Una soluci´on es usar punteros opacos, (aka handles, en C++ se usa tambi´en el nombre Cheshire’s cat). Por ejemplo podr´ıamos ocultar completamente los detalles de Stash como est´a abajo. El usuario s´olo tiene acceso a stashwrapper.h. 1 // Header file stashwrapper.h 2 class StashWrapper { 3 class Stash; 4 Stash *stash; 5 public: 6 void initialize(int size); 7 void cleanup(); 8 int add(void* element); 9 void* fetch(int index); 10 int count(); 11 }; 12 13 // Implementation file stashwrapper.cpp 14 #include "stash.h" Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 189 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 190. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz 15 void StashWrapper::initialize(int size) { 16 stash=new Stash; 17 stash->initialize(); 18 } 19 20 void StashWrapper::cleanup() { 21 stash->cleanup(); 22 delete stash; 23 } 24 25 int StashWrapper::add(void* element) { 26 stash->add(element); 27 } 28 29 //. . . Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 190 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 191. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Inicializaci´on y cleanup Uno de los errores m´as comunes cuando se utilizan librer´ıas es no inicializar y destruir (cleanup) apropiadamente los objetos. En las librer´ıas que hemos descripto hasta ahora esto se hac´ıa con funciones initialize() y cleanup(). Una de las ideas que C++ toma de la OOP es que estas operaciones de inicializaci´on y cleanup se hagan en forma autom´atica. 1 class A { 2 // . . . 3 }; 4 5 void f() { 6 A a; // a is created -> do initialization 7 // Usar a . . . 8 // . . . 9 // . . . 10 } // a is destroyed -> do cleanup Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 191 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 192. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Inicializaci´on y cleanup (cont.) Para esto debe haber dos funciones (una de inicializaci´on y otra de cleanup) que tengan nombres especiales ya que deben ser llamadas autom´aticamente por el compilador. En C++ estas funciones se llaman el constructor y el destructor de la clase. El constructor tiene el mismo nombre que la clase y puede tener argumentos 1 class A { 2 public: 3 A() { /*. . .*/ } 4 // . . . 5 }; 6 7 void f() { 8 A a; // a is created -> calls ctor A::A() 9 // Usar a . . . 10 // . . . 11 } Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 192 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 193. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz El constructor • El ctor puede tener argumentos y puede haber varios constructores. Cual de ellos es utilizado depende del contexto en el que es llamado. • El ctor que no tiene argumentos se llama el constructor por defecto. • No retorna ning´un valor. • Debe ser declarado public para que pueda ser utilizado. • Puede ser privado pero entonces al menos debe tener una clase amiga ya que si no no se podr´ıa construir ning´un objeto de la clase. • Si no declaramos ning´un constructor entonces el compilador sintetiza uno por nosotros y que es el constructor por defecto. Este ctor por defecto no tiene cuerpo, lo ´unico que hace es llamar a los ctores por defecto de cada uno de los miembros (si son clases). Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 193 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 194. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz El destructor • Asi como el constructor garantiza que se llama a la rutina de inicializaci´on, el destructor (abreviado dtor) se encarga de realizar las tareas de cleanup. • Es llamado autom´aticamente cuando termina el scope del objeto. 1 // Constructors & destructors 2 #include <iostream> 3 using namespace std; 4 5 class Tree { 6 int height; 7 public: 8 Tree(int initialHeight); // Constructor 9 ˜Tree(); // Destructor 10 void grow(int years); 11 void printsize(); 12 }; 13 14 Tree::Tree(int initialHeight) { 15 height = initialHeight; 16 } 17 Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 194 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 195. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz 18 Tree::˜Tree() { 19 cout << "inside Tree destructor" << endl; 20 printsize(); 21 } 22 23 void Tree::grow(int years) { 24 height += years; 25 } 26 27 void Tree::printsize() { 28 cout << "Tree height is " << height << endl; 29 } 30 31 int main() { 32 cout << "before opening brace" << endl; 33 { 34 Tree t(12); 35 cout << "after Tree creation" << endl; 36 t.printsize(); 37 t.grow(4); 38 cout << "before closing brace" << endl; 39 } 40 cout << "after closing brace" << endl; 41 } ///:˜ Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 195 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 196. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz El destructor (cont.) Salida del programa: 1 before opening brace 2 after Tree creation 3 Tree height is 12 4 before closing brace 5 inside Tree destructor 6 Tree height is 16 7 after closing brace Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 196 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 197. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Eliminaci´on del bloque de definici´on Es t´ıpico de C tener que definir todas las variables al principio de un scope (por ejemplo de una funci´on). Por el contrario C++ promueve que las variables se definan lo m´as cerca posible del punto en el que van a ser usadas. Esto se pega con el uso autom´atico de constructores, ya que puede ser que el compilador no tenga toda la informaci´on como para llamar al constructor. 1 // Defining variables anywhere 2 #include ". ./require.h" 3 #include <iostream> 4 #include <string> 5 using namespace std; 6 7 class G { 8 int i; 9 public: 10 G(int ii); 11 }; 12 13 G::G(int ii) { i = ii; } 14 15 int main() { 16 cout << "initialization value? "; Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 197 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 198. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz 17 int retval = 0; 18 cin >> retval; 19 require(retval != 0); 20 int y = retval + 3; 21 G g(y); 22 } Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 198 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 199. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Clase stash con ctor/dtor 1 // With constructors & destructors 2 class Stash { 3 int size; // Size of each space 4 int quantity; // Number of storage spaces 5 int next; // Next empty space 6 // Dynamically allocated array of bytes: 7 unsigned char* storage; 8 void inflate(int increase); 9 public: 10 Stash(int size); 11 ˜Stash(); 12 int add(void* element); 13 void* fetch(int index); 14 int count(); 15 }; Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 199 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 200. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Clase stash con ctor/dtor (cont.) 1 //: C06:Stash2.cpp {O} 2 // Constructors & destructors 3 #include "Stash2.h" 4 #include ". ./require.h" 5 #include <iostream> 6 #include <cassert> 7 using namespace std; 8 const int increment = 100; 9 10 Stash::Stash(int sz) { 11 size = sz; 12 quantity = 0; 13 storage = 0; 14 next = 0; 15 } 16 17 int Stash::add(void* element) { 18 if(next >= quantity) // Enough space left? 19 inflate(increment); 20 // Copy element into storage, 21 // starting at next empty space: 22 int startBytes = next * size; Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 200 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 201. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz 23 unsigned char* e = (unsigned char*)element; 24 for(int i = 0; i < size; i++) 25 storage[startBytes + i] = e[i]; 26 next++; 27 return(next - 1); // Index number 28 } 29 30 void* Stash::fetch(int index) { 31 require(0 <= index, "Stash::fetch (-)index"); 32 if(index >= next) 33 return 0; // To indicate the end 34 // Produce pointer to desired element: 35 return &(storage[index * size]); 36 } 37 38 int Stash::count() { 39 return next; // Number of elements in CStash 40 } 41 42 void Stash::inflate(int increase) { 43 require(increase > 0, 44 "Stash::inflate zero or negative increase"); 45 int newQuantity = quantity + increase; 46 int newBytes = newQuantity * size; 47 int oldBytes = quantity * size; Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 201 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 202. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz 48 unsigned char* b = new unsigned char[newBytes]; 49 for(int i = 0; i < oldBytes; i++) 50 b[i] = storage[i]; // Copy old to new 51 delete [ ](storage); // Old storage 52 storage = b; // Point to new memory 53 quantity = newQuantity; 54 } 55 56 Stash::˜Stash() { 57 if(storage != 0) { 58 cout << "freeing storage" << endl; 59 delete [ ]storage; 60 } 61 } Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 202 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 203. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Stack con ctor/dtor 1 // With constructors/destructors 2 #ifndef STACK3-H 3 #define STACK3-H 4 5 class Stack { 6 struct Link { 7 void* data; 8 Link* next; 9 Link(void* dat, Link* nxt); 10 ˜Link(); 11 }* head; 12 public: 13 Stack(); 14 ˜Stack(); 15 void push(void* dat); 16 void* peek(); 17 void* pop(); 18 }; Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 203 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 204. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Stack con ctor/dtor (cont.) 1 #include "Stack3.h" 2 #include ". ./require.h" 3 using namespace std; 4 5 Stack::Link::Link(void* dat, Link* nxt) { 6 data = dat; 7 next = nxt; 8 } 9 10 Stack::Link::˜Link() { } 11 12 Stack::Stack() { head = 0; } 13 14 void Stack::push(void* dat) { 15 head = new Link(dat,head); 16 } 17 18 void* Stack::peek() { 19 require(head != 0, "Stack empty"); 20 return head->data; 21 } 22 23 void* Stack::pop() { 24 if(head == 0) return 0; Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 204 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 205. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz 25 void* result = head->data; 26 Link* oldHead = head; 27 head = head->next; 28 delete oldHead; 29 return result; 30 } 31 32 Stack::˜Stack() { 33 require(head == 0, "Stack not empty"); 34 } ///:˜ Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 205 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 206. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Initializaci´on de agregados • Agregados son arreglos, estructuras y clases. Arreglos son de elementos de un solo tipo, estructuras y clases puede ser de elementos de diferente tipo. • Cuando se define un arreglo se puede inicializar con un juego de valores entre llaves. 1 int a[5] = { 1, 2, 3, 4, 5 }; Inicializa cada uno de las posiciones de a en base a los valores entre llaves. • Inicializa el primero a partir de 17 y todos los dem´as a partir del constructor por defecto 1 int b[6] = {17}; • Conteo autom´atico: autom´aticamente dimensiona c como c[4] a partir del n´umero de elementos entre llaves. 1 int c[ ] = { 1, 2, 3, 4 }; Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 206 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 207. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Inicializaci´on de estructuras 1 struct X { 2 int i; 3 float f; 4 char c; 5 }; 6 7 X x1 = { 1, 2.2, ’c’ }; Se pueden inicializar un arreglo de X al mismo tiempo con doble llaves. 1 X x2[3] = { {1, 1.1, ’a’}, {2, 2.2, ’b’} }; Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 207 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 208. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Sobrecarga de funciones Vimos que el compilador decora los nombres de las funciones que pertenecen a una clase (m´etodos) con el nombre de la clase 1 void f(); 2 class X { void f(); }; Ac´a los nombres de las f no colisionan ya que son en realildad ::f() y X::f(). El compilador tambi´en decora los nombres de las funciones con el tipo de sus argumentos de manera que 1 void print(char); 2 void print(float); no colisionan entre s´ı. (En C esto dar´ıa un error.) Esto se llama sobrecargar el nombre de la funci´on (en este caso print()). Sobrecargar quiere decir entonces usar un mismo nombre para varias cosas diferentes. Atenci´on: NO se puede sobrecargar funciones por el valor de retorno. 1 int f(char c,double x); 2 char f(char c,double x); // ERROR! Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 208 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 209. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Sobrecarga de funciones (cont.) Si compilamos y corremos la utilidad nm al archivo objeto nos da el nombre interno de la funci´on 1 [mstorti@galileo garage]$ nm try22.o 2 U --cxa-atexit 3 U --dso-handle 4 0000000000000010 T main 5 0000000000000000 T -Z1fcd <- This is int f(char c,double d) El mangling _Z1fcd hace que el nombre del del archivo objeto sea ´unico. El lenguaje C no hace mangling, por eso no se puede sobrecargar. Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 209 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 210. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Sobrecarga de funciones (cont.) El nombre mangleado es dif´ıcil de identificar con respecto a la funci´on original. La opci´on nm -C permite obtener un nombre m´as legible. Esto es muy ´util cuando queremos buscar si una librer´ıa tiene una dada funci´on o no. Por otro lado el mangling puede depender del sistema y del compilador, lo cual va en contra de la portabilidad. Es decir no es posible transferir una librer´ıa de C++ compilado con un dado compilador a otro. 1 [mstorti@galileo garage]$ nm -C try22.o | grep f 2 00000000000002d4 t -GLOBAL--sub-I--Z1fcd 3 0000000000000000 T f(char, double) 4 [mstorti@galileo garage]$ Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 210 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 211. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Sobrecarga de funciones (cont.) Por lo tando, cuando definimos varios ctores, estamos sobrecargando el nombre del ctor. 1 class Stash { 2 int size; // Size of each space 3 int quantity; // Number of storage spaces 4 int next; // Next empty space 5 // Dynamically allocated array of bytes: 6 unsigned char* storage; 7 void inflate(int increase); 8 public: 9 Stash(int size); // Zero quantity 10 Stash(int size, int initQuantity); 11 ˜Stash(); 12 int add(void* element); 13 void* fetch(int index); 14 int count(); 15 }; Ahora el ctor Stash(int,int) inicializa el tama˜no del stash a partir del segundo argumento. En cambio recordemos que Stash(int) dejaba al stash vac´ıo. Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 211 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 212. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Argumentos por default Otra posibilidad es que los dos ctores previos sean el mismo con un argumento por default para el tama˜no 1 Stash(int size, int initQuantity = 0); Entonces cuando se usa 1 Stash A(100), B(100, 2000); En el primer llamado es equivalente a A(100,0) Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 212 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 213. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Constantes Objetos de los cuales se supone que su valor no va a variar se pueden definir como constantes 1 #define BUFSIZE 100 // en C 2 const int bufsize = 100; // en C++ (preferible) En el caso de querer ponerlo en un header hay que usar 1 extern const int bufsize; // en un header 2 . . . 3 const int bufsize = 100; // en el .cpp Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 213 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 214. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Constantes (cont.) Otro uso de const es para prometerle al compilador que no se va a modificar esa variable, especialmente con punteros 1 const int* u; Declara que u es un puntero a un int que es constante. De manera que si el compilador detecta que estamos modificando al entero apuntado dar´a un error 1 int x = 23; 2 const int* u; 3 u = &x; 4 *u = 55; // ERROR! Notar que lo que es constante es el valor apuntado, no el puntero en si mismo, el cual es modificado al hacer u = &x. Si queremos que el puntero sea constante entonces hay que hacer 1 int x = 23, z=45; 2 int* const u = &x; 3 u = &z; // ERROR! 4 *u = 55; // OK, modifica x Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 214 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 215. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Constantes (cont.) Tambi´en pueden ser constantes las dos cosas, el puntero y el objeto 1 const int x = 32; 2 const int* const u = &x; C/C++ chequea los tipos, tambien la constancia 1 int d = 1; 2 const int e = 2; 3 int* u = &d; // OK -- d not const 4 int* v = &e; // ERROR! -- e const 5 int* w = (int*)&e; // Legal but bad practice 6 const int* z = &e; // OK Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 215 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 216. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Punteros a arreglos constantes de caracteres 1 char* cp = "Hello world"; // warning!! Como el arreglo de caracteres no fue alocado con new, es constante, o sea que debe ser declarado as´ı 1 const char* cp = "Hello world"; // OK Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 216 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 217. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Const en argumentos de funciones 1 void f(const int i) { 2 i++; // Illegal -- compile-time error 3 } De todas formas no tiene demasiado sentido porque i es pasado por copia. Pero s´ı tiene sentido cuando se pasan argumentos por referencia o por puntero 1 void f(const int *p) { 2 *p = 23; // ERROR! 3 } 4 5 void g(const int &x) { 6 x = 23; // ERROR! 7 } Recordar que pasar por puntero o referencia puede ser para modificar el valor o tambi´en para evitar la copia. Incluyendo el const permite pasar los argumentos en forma eficiente, pero evitando que accidentalmente se modifique el objeto. Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 217 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 218. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Const en clases Si se quiere tener par´ametros de una clase, que son constantes, entonces no s´olo hay que ponerle const, sino tambi´en static que quiere decir que ese miembro es el mismo para todos los objetos de la clase. De esa forma act´ua como una variable global pero protegida por el scope de la clase. Sirve para definir opciones de la clase para poder ser inspeccionadas o modificadas por el usuario. 1 class StringStack { 2 static const int size = 100; 3 const string* stack[size]; 4 int index; 5 public: 6 StringStack(); 7 void push(const string* s); 8 const string* pop(); 9 }; Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 218 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 219. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Objetos const y funciones de la clase Si tenemos una clase A entonces al declarar funciones as´ı 1 void f(const A &a); 2 void g(const A *p); estamos diciendo que no van a modificar el argumento correspondiente. ¿Como hacer lo mismo con los m´etodos de la clase para decir que no modifican al objeto que son aplicados (*this)? 1 class A { 2 public: 3 void f() const; 4 void g(); 5 }; 6 void A::f() const { /* . . . */ } Quiere decir que si hacemos 1 A a; 2 a.f(); podemos estar seguros que la llamada a f() no modifica a a. Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 219 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 220. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Objetos const y funciones de la clase (cont.) Entonces el compilador chequea que si un objeto es const s´olo pueden ser llamados sobre el funciones y m´etodos que no lo modifican, es decir que lo declaran const. 1 const A a1; 2 a1.f(); // OK, f es const 3 a1.g(); // ERROR, g no es const 4 5 void h(A &a) { 6 a.g(); // OK a no es const 7 } 8 9 void h2(const A &a) { 10 a.f(); // OK, f es const 11 a.g(); // ERROR, g no es const 12 } Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 220 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 221. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Chapter 5 Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 221 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 222. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Funciones inline • Cada vez que hay una llamada a funci´on hay un costo adicional de pasar los argumentos por el stack a la funci´on y hacer un jump de assemble. Para evitar esto podemos usar el keyword inline que indica al compilador que queremos que el c´odigo de esa funci´on sea replicado en cada punto en que lo llamamos. • La ventaja, como dijimos, es la eficiencia, se evita el mecanismo de llamado a funci´on en assemble. • La desventaja es que el c´odigo binario de la funci´on aparece duplicado en cada punto, con lo cual el ejecutable se hace m´as grande. Tambi´en implica que el c´odigo de la funci´on debe ser visible (o sea estar en el header) en cada punto en que queremos que sea implementado inline. • El keyword inline es una sugerencia para el compilador. El compilador puede despu´es hacer la funci´on realmente inline o no. A veces puede hacerla no inline porque es muy compleja (e.g. tiene lazos) o porque en alg´un punto se toma la direcci´on de la funci´on. • Funciones definidas en la misma clase (y por lo tanto en el header normalmente) son candidatas a ser promovidas a inline por el compilador. Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 222 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 223. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Funciones inline (cont.) 1 // file: a.hpp 2 // ‘max’ es explicitamente inline 3 // (Notar que si no es inline daria error 4 // al linkeditar por multiple definicion de max()) 5 inline double max(double x,double y) { 6 return (x>y ? x : y); 7 } 8 9 class A { 10 private: 11 int maxsize; 12 public: 13 // Accessors: automaticamente inline 14 int get-maxsize() { return maxsize; } 15 void set-maxsize(int maxsz) { maxsize=maxsz; } 16 //. . . 17 }; Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 223 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 224. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Funciones inline (cont.) Otra forma que habr´ıa para evitar el llamado a funciones ser´ıa no definir la funci´on sino que en cada punto que se usa incluir expl´ıcitamente su c´odigo. Para evitar esto una forma que exist´ıa en C para crear las funciones inline era definir macros, por ejemplo 1 #define MAX(x,y) (x>y ? x : y) Recordar que eso hace que en cada punto del c´odigo final se reemplaze la llamada a MAX por la expansi´on del macro. Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 224 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 225. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Funciones inline (cont.) • OJO, como pasa en general con los macros son peligrosos, Por ejemplo 1 int l = MAX(j++,k); tiene el efecto indeseado que incrementa dos veces a j. • Otro problema es con la precedencia de los operadores. 1 #define SQUARE(x) x*x 2 . . . 3 // Hace a=11!! 4 a = SQUARE(5+1) ya que es completamente equivalente a 1 a = 5+1*5+1 La definici´on apropiada se obtiene protegiendo los argumentos con par´entesis. 1 #define SQUARE(x) (x)*(x) Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 225 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 226. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Especificaciones de linkedicion Cuando declaramos una funci´on, digamos 1 void f(int x, char c); dijimos que internamente el compilador la decora (tambi´en se llama a esto mangling) a, por ejemplo, _Z1fcd. Esto es a efectos de poder despu´es sobrecargar la funci´on. Ahora bien, si queremos usar una librer´ıa de C, entonces ´esta cuando fue compilada no hizo el mangling, y por lo tanto cuando se va a linkeditar no la va a encontrar. Para eso hay que usar el keyword extern al declarar la funci´on 1 extern "C" void f(int x, char c); Esto le dice al compilador que no decore el nombre de esa funci´on. Notar que por lo tanto esa funci´on no puede ser sobrecargada. Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 226 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 227. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Especificaciones de linkedicion (cont.) Como las declaraciones de las librer´ıas estar´an en headers de esas librer´ıas, como hacemos para ponerle un extern "C" a cada una de las funciones del header? Basta con hacerlo externo al include 1 extern "C" { 2 #include <clibheader.h> 3 } Muchos de los headers de librer´ıas de C importantes ya vienen con este tipo de declaraciones de forma de poder ser llamados desde C++, por ejemplo todas las de la libc. Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 227 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 228. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Referencias en C++ Vimos el concepto de referencia, b´asicamente son punteros inteligentes que se autodereferencian. Se pueden implementar funciones que modifican sus argumentos mediante punteros 1 void inc(int *x) { 2 *x = *x + 1, 3 } 4 . . . 5 int a=2; 6 inc(&a); // hace a=3 pero son engorrosos porque hay que ir derereferenciando el puntero. Con referencias es mucho mejor, 1 void inc(int &x) { 2 x = x + 1, 3 } 4 . . . 5 int a=2; 6 inc(a); // hace a=3 Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 228 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 229. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Referencias en C++ (cont.) Otro uso es para crear aliases locales para modificar una parte de un contenedor m´as grande, por ejemplo un arreglo de varias dimensiones (tambi´en puede ser con los contenedores de las STL) 1 class A { 2 // . . . . 3 void f(); // modifica a *this 4 }; 5 6 // arreglo multidimensional de A’s 7 A av[100][100][100]; 8 // Un elemento particular de av 9 int i,j,k; 10 //. . . 11 av[i][j][k].f(); Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 229 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 230. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Referencias en C++ (cont.) Si queremos manipular mucho a ese elemento particular de av entonces en cada punto hay que poner av[i][j][k]. Si fuera un tipo simple, como un int o un double, entonces podr´ıamos crear una copia local y despu´es pisar el valor en av 1 // arreglo multidimensional de A’s 2 int v[100][100][100]; 3 // Un elemento particular de av 4 int x = v[i][j][k]; 5 // . . . hace calculos con x 6 // Pisa el valor en av 7 v[i][j][k] = x; Pero si A es una clase complicada esto implica hacer una copia del objeto, lo cual es ineficiente y incluso puede ser que no podamos hacer copias del objeto. Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 230 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 231. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Referencias en C++ (cont.) De nuevo, una posibilidad es usar macros 1 // arreglo multidimensional de A’s 2 A av[100][100][100]; 3 // Un elemento particular de av 4 int i,j,k; 5 #define AIJK av[i][j][k] 6 //. . . 7 AIJK.f(); Como siempre, los macros son peligrosos y hay que tratar de no usarlos. Adem´as cada vez que llamamos a AIJK estamos haciendo una cuenta con i,j,k para encontrar la posici´on correspondiente en v. Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 231 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 232. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Referencias en C++ (cont.) Una posibilidad es usar punteros 1 // arreglo multidimensional de A’s 2 A av[100][100][100]; 3 // Un elemento particular de av 4 int i,j,k; 5 A *ap = &av[i][j][k]; 6 7 ap->f(); Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 232 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 233. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Referencias en C++ (cont.) Esto es eficiente, y compacto pero hay que andar dereferenciando ap. Todav´ıa mejor es usar referencias 1 // arreglo multidimensional de A’s 2 A av[100][100][100]; 3 // Un elemento particular de av 4 int i,j,k; 5 A &a = av[i][j][k]; 6 7 a.f(); Es eficiente, limpio, y a se manipula como un objeto m´as de la clase. Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 233 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 234. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Reglas para las referencias • Las referencias deben ser inicializadas cuando son creadas 1 A &a = av[i][j][k]; // OK 2 3 A &a; // ERROR (No incluye inicializacion) 4 a = av[i][j][k]; • Una vez que una referencia apunta a un objeto, no se lo puede hacer apuntar a otro 1 A &a = av[i][j][k]; 2 a = av[l][m][n]; // compila OK, pero no reposiciona 3 // la referencia, simplemente hace 4 // una copia del elemento l,m,n al i,j,k Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 234 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 235. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Reglas para las referencias (cont.) Lo que SI se puede hacer es ir creando referencias con el mismo nombre a diferentes objetos 1 for (int i=0; i<N; i++) { 2 for (int j=0; j<N; j++) { 3 for (int k=0; k<N; k++) { 4 A &a = av[i][j][k]; 5 // manipula av[i][j][k] a trav´es de a 6 } 7 } 8 } • No se puede hacer una referencia a NULL. • Hacer referencias es muy eficiente, igual que con punteros. Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 235 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 236. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Paso por referencia y por copia Normalmente uno escribe el paso de argumentos por copia 1 void f(A a, B b) {. . .} Esto es ineficiente y adem´as requiere que las clases A, B implementen el constructor por copia A(A&), B(B&) (en general se le llama X(X&)). 1 class A { 2 //. . . 3 A(A&) { . . . } // Constructor por copia 4 }; Para evitar esto ya mencionamos que se puede pasar por referencia 1 void f(A &a, B &b) {. . .} Si la funci´on no va a modificar los argumentos es todav´ıa mejor declarar a las referencias como const 1 void f(const A &a,const B &b) {. . .} Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 236 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 237. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz El constructor por copia • Vimos que al pasar objetos a funciones por copia se llama al constructor por copia. • Si la clase no define al constructor por copia el compilador sintetiza uno por nosotros (haciendo copia bit-a-bit). • Esto se llama una shallow copy (por contraposici´on con una deep copy) y puede traer problemas, sobre todo si el objeto contiene punteros a ´areas de almacenamiento din´amico alocados con new. • O bien hay que implementar el constructor por copia haciendo la deep copy o bien hay que prohibirlo declarando al constructor por copia privado 1 class A { 2 private: 3 A(A&) {} 4 } 5 6 void f(A a) { // ERROR, llama al ctor por copia 7 } Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 237 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 238. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Sobrecarga de operadores • Sobrecarga de operadores es simplemente un aditivo sint´actico (sintactic sugar) para hacer llamadas a funciones de la clase en forma m´as compacta. • Los nombres de los operadores son operator@ donde @ puede ser algunos de los operadores usuales, matem´aticos (+, -, *, /), de indexaci´on [], (), incremento ++, --, acumulaci´on (+=, -=, *=, /=), l´ogicos ||, &&, etc... • Hay operadores unarios y binarios. A veces el mismo operador puede ser unario o binario dependiendo del contexto (por ejemplo * (dereferenciaci´on como unario, producto como binario), +, -). • Cu´al de los operadores es llamado y sobre que objetos es a veces un poco dif´ıcil de discernir. • Pueden ser m´etodos de la clase o pueden ser funciones globales (declaradas friend) Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 238 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 239. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Sobrecarga de operadores (cont.) En el caso de operadores unarios, el objeto al cual se aplica el operador pasa a ser *this 1 class A { 2 A operator*(const A& right) { . . . } // producto (1) 3 }; 4 5 class HandleToA { 6 A &operator*() { . . . } // dereferenciacion (2) 7 }; 8 9 A a1, a2, a3; 10 HandleToA p; 11 12 a1 = a2*a3; // llama a (1) con *this = a2, 13 // right = a3 y el valor de retorno 14 // es asignado a a1 15 a1 = *p; // llama a (2) con *this = p Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 239 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 240. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Sobrecarga de operadores (cont.) 1 #include <iostream> 2 using namespace std; 3 4 class Integer { 5 int i; 6 public: 7 Integer(int ii) : i(ii) {} 8 const Integer 9 operator+(const Integer& rv) const { 10 cout << "operator+" << endl; 11 return Integer(i + rv.i); 12 } 13 Integer& 14 operator+=(const Integer& rv) { 15 cout << "operator+=" << endl; 16 i += rv.i; 17 return *this; 18 } 19 }; 20 21 int main() { 22 cout << "built-in types:" << endl; Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 240 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 241. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz 23 int i = 1, j = 2, k = 3; 24 k += i + j; 25 cout << "user-defined types:" << endl; 26 Integer ii(1), jj(2), kk(3); 27 kk += ii + jj; 28 } Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 241 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 242. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Sobrecarga de operadores (cont.) • Se pueden sobrecargar buena parte de los operadores que ya existen en C. • No se pueden inventar nuevos operadores (e.g. usar ** para la exponenciaci´on, como en Fortran). • No se puede cambiar la regla de precedencia de los operadores. Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 242 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 243. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Sobrecarga de operadores unarios 1 #include <iostream> 2 using namespace std; 3 4 // Non-member functions: 5 class Integer { 6 long i; 7 Integer* This() { return this; } 8 public: 9 Integer(long ll = 0) : i(ll) {} 10 // No side effects takes const& argument: 11 friend const Integer& 12 operator+(const Integer& a); 13 friend const Integer 14 operator-(const Integer& a); 15 friend const Integer 16 operator˜(const Integer& a); 17 friend Integer* 18 operator&(Integer& a); 19 friend int 20 operator!(const Integer& a); 21 // Side effects have non-const& argument: Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 243 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 244. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz 22 // Prefix: 23 friend const Integer& 24 operator++(Integer& a); 25 // Postfix: 26 friend const Integer 27 operator++(Integer& a, int); 28 // Prefix: 29 friend const Integer& 30 operator--(Integer& a); 31 // Postfix: 32 friend const Integer 33 operator--(Integer& a, int); 34 }; 35 36 // Global operators: 37 const Integer& operator+(const Integer& a) { 38 cout << "+Integern"; 39 return a; // Unary + has no effect 40 } 41 const Integer operator-(const Integer& a) { 42 cout << "-Integern"; 43 return Integer(-a.i); 44 } 45 const Integer operator˜(const Integer& a) { Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 244 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 245. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz 46 cout << "˜Integern"; 47 return Integer(˜a.i); 48 } 49 Integer* operator&(Integer& a) { 50 cout << "&Integern"; 51 return a.This(); // &a is recursive! 52 } 53 int operator!(const Integer& a) { 54 cout << "bang Integern"; 55 return !a.i; 56 } 57 // Prefix; return incremented value 58 const Integer& operator++(Integer& a) { 59 cout << "++Integern"; 60 a.i++; 61 return a; 62 } 63 // Postfix; return the value before increment: 64 const Integer operator++(Integer& a, int) { 65 cout << "Integer++n"; 66 Integer before(a.i); 67 a.i++; 68 return before; Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 245 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 246. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz 69 } 70 // Prefix; return decremented value 71 const Integer& operator--(Integer& a) { 72 cout << "--Integern"; 73 a.i--; 74 return a; 75 } 76 // Postfix; return the value before decrement: 77 const Integer operator--(Integer& a, int) { 78 cout << "Integer--n"; 79 Integer before(a.i); 80 a.i--; 81 return before; 82 } 83 84 // Show that the overloaded operators work: 85 void f(Integer a) { 86 +a; 87 -a; 88 ˜a; 89 Integer* ip = &a; 90 !a; 91 ++a; 92 a++; 93 --a; Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 246 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 247. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz 94 a--; 95 } 96 97 // Member functions (implicit ‘‘this’’): 98 class Byte { 99 unsigned char b; 100 public: 101 Byte(unsigned char bb = 0) : b(bb) {} 102 // No side effects: const member function: 103 const Byte& operator+() const { 104 cout << "+Byten"; 105 return *this; 106 } 107 const Byte operator-() const { 108 cout << "-Byten"; 109 return Byte(-b); 110 } 111 const Byte operator˜() const { 112 cout << "˜Byten"; 113 return Byte(˜b); 114 } 115 Byte operator!() const { 116 cout << "bang Byten"; 117 return Byte(!b); Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 247 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 248. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz 118 } 119 Byte* operator&() { 120 cout << "&Byten"; 121 return this; 122 } 123 // Side effects: non-const member function: 124 const Byte& operator++() { // Prefix 125 cout << "++Byten"; 126 b++; 127 return *this; 128 } 129 const Byte operator++(int) { // Postfix 130 cout << "Byte++n"; 131 Byte before(b); 132 b++; 133 return before; 134 } 135 const Byte& operator--() { // Prefix 136 cout << "--Byten"; 137 --b; 138 return *this; 139 } 140 const Byte operator--(int) { // Postfix 141 cout << "Byte--n"; Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 248 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 249. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz 142 Byte before(b); 143 --b; 144 return before; 145 } 146 }; 147 148 void g(Byte b) { 149 +b; 150 -b; 151 ˜b; 152 Byte* bp = &b; 153 !b; 154 ++b; 155 b++; 156 --b; 157 b--; 158 } 159 160 int main() { 161 Integer a; 162 f(a); 163 Byte b; 164 g(b); 165 } ///:˜ Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 249 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 250. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Sobrecarga de operadores unarios (cont.) Operadores ++ y -- prefijo y postfijo: Recordemos que hay dos versiones del operador ++, cuando hacemos i++ y ++i, ambos se pueden sobrecargar con el operador operator++() pero como hacer para diferenciarlos? El prefijo es operator++() y el postfijo es operator++(int). Notar que el argumento int para el postfijo no se usa y por lo tanto no hace falta pasarle el argumento dummy correspondiente. Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 250 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 251. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Sobrecarga de operadores binarios 1 // Non-member overloaded operators 2 #include <iostream> 3 4 // Non-member functions: 5 class Integer { 6 long i; 7 public: 8 Integer(long ll = 0) : i(ll) {} 9 // Operators that create new, modified value: 10 friend const Integer 11 operator+(const Integer& left, 12 const Integer& right); 13 friend const Integer 14 operator-(const Integer& left, 15 const Integer& right); 16 friend const Integer 17 operator*(const Integer& left, 18 const Integer& right); 19 friend const Integer 20 operator/(const Integer& left, 21 const Integer& right); Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 251 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 252. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz 22 friend const Integer 23 operator%(const Integer& left, 24 const Integer& right); 25 friend const Integer 26 operatorˆ(const Integer& left, 27 const Integer& right); 28 friend const Integer 29 operator&(const Integer& left, 30 const Integer& right); 31 friend const Integer 32 operator|(const Integer& left, 33 const Integer& right); 34 friend const Integer 35 operator<<(const Integer& left, 36 const Integer& right); 37 friend const Integer 38 operator>>(const Integer& left, 39 const Integer& right); 40 // Assignments modify & return lvalue: 41 friend Integer& 42 operator+=(Integer& left, 43 const Integer& right); 44 friend Integer& Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 252 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 253. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz 45 operator-=(Integer& left, 46 const Integer& right); 47 friend Integer& 48 operator*=(Integer& left, 49 const Integer& right); 50 friend Integer& 51 operator/=(Integer& left, 52 const Integer& right); 53 friend Integer& 54 operator%=(Integer& left, 55 const Integer& right); 56 friend Integer& 57 operatorˆ=(Integer& left, 58 const Integer& right); 59 friend Integer& 60 operator&=(Integer& left, 61 const Integer& right); 62 friend Integer& 63 operator|=(Integer& left, 64 const Integer& right); 65 friend Integer& 66 operator>>=(Integer& left, 67 const Integer& right); Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 253 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 254. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz 68 friend Integer& 69 operator<<=(Integer& left, 70 const Integer& right); 71 // Conditional operators return true/false: 72 friend int 73 operator==(const Integer& left, 74 const Integer& right); 75 friend int 76 operator!=(const Integer& left, 77 const Integer& right); 78 friend int 79 operator<(const Integer& left, 80 const Integer& right); 81 friend int 82 operator>(const Integer& left, 83 const Integer& right); 84 friend int 85 operator<=(const Integer& left, 86 const Integer& right); 87 friend int 88 operator>=(const Integer& left, 89 const Integer& right); 90 friend int 91 operator&&(const Integer& left, Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 254 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 255. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz 92 const Integer& right); 93 friend int 94 operator| |(const Integer& left, 95 const Integer& right); 96 // Write the contents to an ostream: 97 void print(std::ostream& os) const { os << i; } 98 }; 99 #endif // INTEGER-H ///:˜ 100 101 //: C12:Integer.cpp {O} 102 // Implementation of overloaded operators 103 #include "Integer.h" 104 #include ". ./require.h" 105 106 const Integer 107 operator+(const Integer& left, 108 const Integer& right) { 109 return Integer(left.i + right.i); 110 } 111 const Integer 112 operator-(const Integer& left, 113 const Integer& right) { 114 return Integer(left.i - right.i); 115 } 116 const Integer Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 255 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 256. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz 117 operator*(const Integer& left, 118 const Integer& right) { 119 return Integer(left.i * right.i); 120 } 121 const Integer 122 operator/(const Integer& left, 123 const Integer& right) { 124 require(right.i != 0, "divide by zero"); 125 return Integer(left.i / right.i); 126 } 127 const Integer 128 operator%(const Integer& left, 129 const Integer& right) { 130 require(right.i != 0, "modulo by zero"); 131 return Integer(left.i % right.i); 132 } 133 const Integer 134 operatorˆ(const Integer& left, 135 const Integer& right) { 136 return Integer(left.i ˆ right.i); 137 } 138 const Integer 139 operator&(const Integer& left, Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 256 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 257. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz 140 const Integer& right) { 141 return Integer(left.i & right.i); 142 } 143 const Integer 144 operator|(const Integer& left, 145 const Integer& right) { 146 return Integer(left.i | right.i); 147 } 148 const Integer 149 operator<<(const Integer& left, 150 const Integer& right) { 151 return Integer(left.i << right.i); 152 } 153 const Integer 154 operator>>(const Integer& left, 155 const Integer& right) { 156 return Integer(left.i >> right.i); 157 } 158 // Assignments modify & return lvalue: 159 Integer& operator+=(Integer& left, 160 const Integer& right) { 161 if(&left == &right) {/* self-assignment */} 162 left.i += right.i; Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 257 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 258. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz 163 return left; 164 } 165 Integer& operator-=(Integer& left, 166 const Integer& right) { 167 if(&left == &right) {/* self-assignment */} 168 left.i -= right.i; 169 return left; 170 } 171 Integer& operator*=(Integer& left, 172 const Integer& right) { 173 if(&left == &right) {/* self-assignment */} 174 left.i *= right.i; 175 return left; 176 } 177 Integer& operator/=(Integer& left, 178 const Integer& right) { 179 require(right.i != 0, "divide by zero"); 180 if(&left == &right) {/* self-assignment */} 181 left.i /= right.i; 182 return left; 183 } 184 Integer& operator%=(Integer& left, 185 const Integer& right) { Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 258 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 259. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz 186 require(right.i != 0, "modulo by zero"); 187 if(&left == &right) {/* self-assignment */} 188 left.i %= right.i; 189 return left; 190 } 191 Integer& operatorˆ=(Integer& left, 192 const Integer& right) { 193 if(&left == &right) {/* self-assignment */} 194 left.i ˆ= right.i; 195 return left; 196 } 197 Integer& operator&=(Integer& left, 198 const Integer& right) { 199 if(&left == &right) {/* self-assignment */} 200 left.i &= right.i; 201 return left; 202 } 203 Integer& operator|=(Integer& left, 204 const Integer& right) { 205 if(&left == &right) {/* self-assignment */} 206 left.i |= right.i; 207 return left; 208 } Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 259 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 260. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz 209 Integer& operator>>=(Integer& left, 210 const Integer& right) { 211 if(&left == &right) {/* self-assignment */} 212 left.i >>= right.i; 213 return left; 214 } 215 Integer& operator<<=(Integer& left, 216 const Integer& right) { 217 if(&left == &right) {/* self-assignment */} 218 left.i <<= right.i; 219 return left; 220 } 221 // Conditional operators return true/false: 222 int operator==(const Integer& left, 223 const Integer& right) { 224 return left.i == right.i; 225 } 226 int operator!=(const Integer& left, 227 const Integer& right) { 228 return left.i != right.i; 229 } 230 int operator<(const Integer& left, 231 const Integer& right) { Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 260 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 261. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz 232 return left.i < right.i; 233 } 234 int operator>(const Integer& left, 235 const Integer& right) { 236 return left.i > right.i; 237 } 238 int operator<=(const Integer& left, 239 const Integer& right) { 240 return left.i <= right.i; 241 } 242 int operator>=(const Integer& left, 243 const Integer& right) { 244 return left.i >= right.i; 245 } 246 int operator&&(const Integer& left, 247 const Integer& right) { 248 return left.i && right.i; 249 } 250 int operator| |(const Integer& left, 251 const Integer& right) { 252 return left.i | | right.i; 253 } ///:˜ 254 255 //: C12:IntegerTest.cpp Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 261 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 262. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz 256 //{L} Integer 257 #include "Integer.h" 258 #include <fstream> 259 using namespace std; 260 ofstream out("IntegerTest.out"); 261 262 void h(Integer& c1, Integer& c2) { 263 // A complex expression: 264 c1 += c1 * c2 + c2 % c1; 265 #define TRY(OP) 266 out << "c1 = "; c1.print(out); 267 out << ", c2 = "; c2.print(out); 268 out << "; c1 " #OP " c2 produces "; 269 (c1 OP c2).print(out); 270 out << endl; 271 TRY(+) TRY(-) TRY(*) TRY(/) 272 TRY(%) TRY(ˆ) TRY(&) TRY(|) 273 TRY(<<) TRY(>>) TRY(+=) TRY(-=) 274 TRY(*=) TRY(/=) TRY(%=) TRY(ˆ=) 275 TRY(&=) TRY(|=) TRY(>>=) TRY(<<=) 276 // Conditionals: 277 #define TRYC(OP) 278 out << "c1 = "; c1.print(out); 279 out << ", c2 = "; c2.print(out); Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 262 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 263. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz 280 out << "; c1 " #OP " c2 produces "; 281 out << (c1 OP c2); 282 out << endl; 283 TRYC(<) TRYC(>) TRYC(==) TRYC(!=) TRYC(<=) 284 TRYC(>=) TRYC(&&) TRYC(| |) 285 } 286 287 int main() { 288 cout << "friend functions" << endl; 289 Integer c1(47), c2(9); 290 h(c1, c2); 291 } ///:˜ 292 293 //: C12:Byte.h 294 // Member overloaded operators 295 #ifndef BYTE-H 296 #define BYTE-H 297 #include ". ./require.h" 298 #include <iostream> 299 // Member functions (implicit ‘‘this’’): 300 class Byte { 301 unsigned char b; 302 public: 303 Byte(unsigned char bb = 0) : b(bb) {} Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 263 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 264. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz 304 // No side effects: const member function: 305 const Byte 306 operator+(const Byte& right) const { 307 return Byte(b + right.b); 308 } 309 const Byte 310 operator-(const Byte& right) const { 311 return Byte(b - right.b); 312 } 313 const Byte 314 operator*(const Byte& right) const { 315 return Byte(b * right.b); 316 } 317 const Byte 318 operator/(const Byte& right) const { 319 require(right.b != 0, "divide by zero"); 320 return Byte(b / right.b); 321 } 322 const Byte 323 operator%(const Byte& right) const { 324 require(right.b != 0, "modulo by zero"); 325 return Byte(b % right.b); 326 } 327 const Byte Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 264 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 265. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz 328 operatorˆ(const Byte& right) const { 329 return Byte(b ˆ right.b); 330 } 331 const Byte 332 operator&(const Byte& right) const { 333 return Byte(b & right.b); 334 } 335 const Byte 336 operator|(const Byte& right) const { 337 return Byte(b | right.b); 338 } 339 const Byte 340 operator<<(const Byte& right) const { 341 return Byte(b << right.b); 342 } 343 const Byte 344 operator>>(const Byte& right) const { 345 return Byte(b >> right.b); 346 } 347 // Assignments modify & return lvalue. 348 // operator= can only be a member function: 349 Byte& operator=(const Byte& right) { 350 // Handle self-assignment: Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 265 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 266. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz 351 if(this == &right) return *this; 352 b = right.b; 353 return *this; 354 } 355 Byte& operator+=(const Byte& right) { 356 if(this == &right) {/* self-assignment */} 357 b += right.b; 358 return *this; 359 } 360 Byte& operator-=(const Byte& right) { 361 if(this == &right) {/* self-assignment */} 362 b -= right.b; 363 return *this; 364 } 365 Byte& operator*=(const Byte& right) { 366 if(this == &right) {/* self-assignment */} 367 b *= right.b; 368 return *this; 369 } 370 Byte& operator/=(const Byte& right) { 371 require(right.b != 0, "divide by zero"); 372 if(this == &right) {/* self-assignment */} 373 b /= right.b; Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 266 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 267. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz 374 return *this; 375 } 376 Byte& operator%=(const Byte& right) { 377 require(right.b != 0, "modulo by zero"); 378 if(this == &right) {/* self-assignment */} 379 b %= right.b; 380 return *this; 381 } 382 Byte& operatorˆ=(const Byte& right) { 383 if(this == &right) {/* self-assignment */} 384 b ˆ= right.b; 385 return *this; 386 } 387 Byte& operator&=(const Byte& right) { 388 if(this == &right) {/* self-assignment */} 389 b &= right.b; 390 return *this; 391 } 392 Byte& operator|=(const Byte& right) { 393 if(this == &right) {/* self-assignment */} 394 b |= right.b; 395 return *this; 396 } Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 267 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 268. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz 397 Byte& operator>>=(const Byte& right) { 398 if(this == &right) {/* self-assignment */} 399 b >>= right.b; 400 return *this; 401 } 402 Byte& operator<<=(const Byte& right) { 403 if(this == &right) {/* self-assignment */} 404 b <<= right.b; 405 return *this; 406 } 407 // Conditional operators return true/false: 408 int operator==(const Byte& right) const { 409 return b == right.b; 410 } 411 int operator!=(const Byte& right) const { 412 return b != right.b; 413 } 414 int operator<(const Byte& right) const { 415 return b < right.b; 416 } 417 int operator>(const Byte& right) const { 418 return b > right.b; 419 } Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 268 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 269. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz 420 int operator<=(const Byte& right) const { 421 return b <= right.b; 422 } 423 int operator>=(const Byte& right) const { 424 return b >= right.b; 425 } 426 int operator&&(const Byte& right) const { 427 return b && right.b; 428 } 429 int operator| |(const Byte& right) const { 430 return b | | right.b; 431 } 432 // Write the contents to an ostream: 433 void print(std::ostream& os) const { 434 os << "0x" << std::hex << int(b) << std::dec; 435 } 436 }; 437 #endif // BYTE-H ///:˜ 438 439 //: C12:ByteTest.cpp 440 #include "Byte.h" 441 #include <fstream> 442 using namespace std; 443 ofstream out("ByteTest.out"); Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 269 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 270. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz 444 445 void k(Byte& b1, Byte& b2) { 446 b1 = b1 * b2 + b2 % b1; 447 448 #define TRY2(OP) 449 out << "b1 = "; b1.print(out); 450 out << ", b2 = "; b2.print(out); 451 out << "; b1 " #OP " b2 produces "; 452 (b1 OP b2).print(out); 453 out << endl; 454 455 b1 = 9; b2 = 47; 456 TRY2(+) TRY2(-) TRY2(*) TRY2(/) 457 TRY2(%) TRY2(ˆ) TRY2(&) TRY2(|) 458 TRY2(<<) TRY2(>>) TRY2(+=) TRY2(-=) 459 TRY2(*=) TRY2(/=) TRY2(%=) TRY2(ˆ=) 460 TRY2(&=) TRY2(|=) TRY2(>>=) TRY2(<<=) 461 TRY2(=) // Assignment operator 462 463 // Conditionals: 464 #define TRYC2(OP) 465 out << "b1 = "; b1.print(out); 466 out << ", b2 = "; b2.print(out); 467 out << "; b1 " #OP " b2 produces "; 468 out << (b1 OP b2); Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 270 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 271. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz 469 out << endl; 470 471 b1 = 9; b2 = 47; 472 TRYC2(<) TRYC2(>) TRYC2(==) TRYC2(!=) TRYC2(<=) 473 TRYC2(>=) TRYC2(&&) TRYC2(| |) 474 475 // Chained assignment: 476 Byte b3 = 92; 477 b1 = b2 = b3; 478 } 479 480 int main() { 481 out << "member functions:" << endl; 482 Byte b1(47), b2(9); 483 k(b1, b2); 484 } ///:˜ Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 271 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 272. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Sobrecarga de operadores binarios (cont.) • En los operadores de acumulaci´on (e.g. operator+=) se tiene que 1 Integer& operator+=(Integer& left, 2 const Integer& right) { 3 if(&left == &right) {/* self-assignment */} 4 left.i += right.i; 5 return left; 6 } 7 // . . . 8 Integer R,L; 9 L += R; Tenemos que left es L, right es R. Hay que tener cuidado porque el L y R podr´ıan ser el mismo objeto, por ejemplo si hacemos 1 Integer A; 2 A += A; Lo mismo pasa con el operador de asignaci´on operator=(). A esto se le llama chequear por autoasignaci´on. Sobre todo si hay componentes apuntadas por punteros. Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 272 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 273. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Chapter Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 273 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 274. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Otros operadores que se pueden sobrecargar • operator[]: Se usa normalmente para emular lo que ocurre al indexar un vector por un entero. En las STL se usa en las clases vector<> y map<> • operator(): Se usa para emular que el objeto act´ua como una funci´on (functor). • operator*, operator->: Se utilizan para emular el comportamiento de los punteros (por ejemplo los smart pointers). En las STL se usan para los iterators de los diferentes contenedores. Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 274 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 275. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Creaci´on din´amica de objetos Las variables de un programa pueden ser alocados en tres formas diferentes y normalmente viven en secciones diferentes de memoria • Objetos globales y est´aticos son alocados en el momento de arrancar el programa y viven durante toda la duraci´on del mismo. • Objetos din´amicos son alocados al entrar en el scope correspondiente. La alocaci´on se hace en el stack. • Objetos pueden ser alocados y desalocados en cualquier momento (responsabilidad del programador) en el heap. Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 275 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 276. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Uso de la memoria din´amica en C En C la alocaci´on en el heap se hace con las funciones malloc() y free(). El uso b´asico para objetos en C ser´ıa as´ı 1 struct A { }; 2 3 A *p = (A*)malloc(sizeof(A)); 4 A-initialize(p); 5 // . . . . usa *p 6 A-destroy(p); 7 free(p); Hay varios puntos donde esto puede fallar, por un error del programador: • No alocar apropiadamente la memoria apropiada para el objeto. • No convertir el puntero al tipo apropiado. • No inicializar el objeto. • No destruir el objeto. • No liberar la memoria alocada. Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 276 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 277. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Uso de la memoria din´amica en C++ En C++ se trata que todas estas acciones sean hechas en lo posible en forma autom´atica por el operador. Para esto las funciones malloc() y free() (que despu´es de todo son funciones de librer´ıa es decir que no son parte del lenguaje) son reemplazadas por operadores intr´ınsecos del lenguaje: new y delete. 1 A *p = new A; 2 // . . . usa *p 3 delete p; new A se encarga de alocar el espacio apropiado (sizeof(A), castear al tipo correcto (A*) e inicializar (llamar al constructor). delete p se encarga de llamar al destructor y liberar la memoria alocada. Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 277 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 278. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Uso de la memoria din´amica en C++ (cont.) Como new se encarga de la inicializaci´on, tambi´en se puede llamar con cualquier otro constructor, adem´as del ctor por defecto 1 A *p = new A(x,y,z); Tambi´en se pueden alocar arreglos de objetos 1 A *av = new A[100]; En este caso el compilador se encarga de alocar el espacio para los 100 objetos y llamar al constructor por defecto sobre cada uno de ellos. No hay forma de inicializar arreglos con un constructor que no sea el ctor por defecto. Recordar que para arreglos se puede inicializar expl´ıcitamente cada objeto (pero no todos al mismo tiempo) 1 A av[4] = {1,2,3} Para el cuarto (av[3]) usa el constructor por defecto. Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 278 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 279. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Porqu´e usar new y no arreglos 1 A av1[20]; // OK la dimension es una cte 2 3 const int m=100; 4 A av1[m]; // OK la dimension es una cte 5 6 int n=100; 7 A a[n]; // ERROR El ´ultimo deber´ıa dar error de compilaci´on aunque dependiendo del compilador puede que no lo de (ser´ıa una extensi´on del compilador). De todas formas siempre es m´as restrictivo que alocar con new porque el arreglo es desalocado y destruido cuando termina su scope. Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 279 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 280. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Memory exhaust Qu´e ocurre si se acaba la memoria? En viejos compiladores new retornaba un puntero nulo. En el est´andar actual lanza una excepci´on de tipo bad_alloc(). Por compatibilidad con la versi´on antigua se le puede usar new(std::nothrow) que emula el primer comportamiento. 1 try { // version ‘throw’ 2 int *p = new int[N]; 3 // alocacion exitosa, usar p. . . 4 } catch(bad-alloc) { 5 cout << "error" << endl; 6 break; 7 } 8 9 // version ‘nothrow’ 10 int *p = new(std::nothrow) int[N]; 11 if (!p) { 12 // error. . . 13 } Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 280 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 281. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Composici´on Hasta ahora vimos clases/estructuras que se construyen a partir de tipos b´asicos usando composici´on. 1 class A { 2 private: 3 int i; 4 double x; 5 public: 6 char c; 7 void f(); 8 }; Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 281 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 282. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Composici´on (cont.) La idea es que las clases de objetos se pueden usar como nuevos tipos, por lo tanto se pueden usar en la composici´on de otros tipos 1 class B { 2 private: 3 int k; 4 double z; 5 public: 6 A a; 7 void g(); 8 }; En este caso B::a es p´ublico, de forma que los m´etodos p´ublicos de A tambi´en se pueden llamar sobre este campo, es decir 1 B b; 2 b.a.f(); // OK Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 282 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 283. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Composici´on y la cadena de inicializaci´on Hemos visto que en el constructor de la clase podemos inicializar sus miembros en la cadena de inicializaci´on. En particular tambi´en se pueden llamar constructores de los subobjetos que forman parte de la clase 1 class B { 2 private: 3 int k; 4 double z; 5 public: 6 B() : a(234,"jaja") { } 7 A a; 8 void g(); 9 }; En la cadena de inicializaci´on se pueden poner tanto constructores de subobjetos como tambi´en inicializar objetos built-in (int, double...) por copia. Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 283 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 284. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Herencia Otra forma de elaborar clases m´as complejas a partir de otras m´as simples es por herencia. 1 class C : public A { 2 int k; 3 double z; 4 public: 5 void g(); 6 }; Se dice que C es una clase derivada de A y A es la clase base de C. Los m´etodos de A se pueden llamar ahora tambi´en sobre C. en este caso estamos diciendo C es como A pero tiene algunas cosas adicionales. Al hacer composici´on estamos diciendo que C contiene a un objeto de tipo A. Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 284 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 285. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Herencia (cont.) Notar que en el caso de composici´on los miembros de A se acceden a trav´es de B::a, es decir por ejemplo 1 B b; 2 b.a.c = ’5’; mientras que en el caso de herencia, no existe directamente el miembro B::a de manera que los miembros de A pasan a ser directamente miembros de C 1 C c; 2 c.c = ’7’; Al declarar en la herencia que A es p´ublico, todos los miembros y m´etodos de A ser´an vistos a trav´es de C con la privacidad que ten´ıan en A, es decir C.c es p´ublico y C.i es privado. Por el contrario, si declaramos 1 class C : private A { . . . entonces todos los campos de A son privados. Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 285 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 286. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Herencia (cont.) Notar que con composici´on se pueden incluir en la nueva clase muchos objetos del mismo tipo o de diferente tipo, mientras que con herencia no es usual derivar de varias clases al mismo tiempo. 1 class A { . . . . }; 2 class X { . . . . }; 3 4 class B { 5 A a1,a2; 6 X x; 7 // . . . 8 }; Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 286 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 287. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Redefinici´on de m´etodos ¿Qu´e pasa si la clase derivada tiene un m´etodo con el mismo nombre que la clase base? Con composici´on no hay problema 1 class A { 2 public: 3 void f(); 4 }; 5 6 class B { 7 public: 8 A a; 9 void f(); 10 }; 11 12 B b; 13 b.f(); // llama la f de B 14 b.a.f(); // llama la f de A Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 287 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 288. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Redefinici´on de m´etodos (cont.) Con herencia el nuevo m´etodo redefine u oculta el m´etodo anterior 1 class A { 2 public: 3 void f(); 4 }; 5 6 class B : public A { 7 public: 8 void f(); 9 }; 10 11 B b; 12 b.f(); // llama la f de B 13 b.A::f(); // llama la f de A Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 288 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 289. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Herencia protegida Hay una forma de herencia que es intermedia entre p´ublico y privado, y es la herencia protected. En este caso lo m´etodos de la clase son privados para el exterior pero pueden ser usados como p´ublicos por la base derivada. 1 class Base { 2 int i; 3 protected: 4 int read() const { return i; } 5 void set(int ii) { i = ii; } 6 public: 7 Base(int ii = 0) : i(ii) {} 8 int value(int m) const { return m*i; } 9 }; 10 11 class Derived : public Base { 12 int j; 13 public: 14 Derived(int jj = 0) : j(jj) {} 15 void change(int x) { set(x); } 16 }; 17 Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 289 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 290. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz 18 int main() { 19 Derived d; 20 d.change(10); 21 } Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 290 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 291. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Upcasting El compilador nos deja sin problema castear un puntero de la clase derivada a la clase base, porque sabe que la clase derivada tiene todas las cosas de la base 1 class Base { //. . . 2 3 class Derived : public Base { . . . 4 5 Derived d1, d2; 6 Base &b = d1; 7 Base *p = &d2; Esto se llama upcasting. Sin embargo, si llamamos a un m´etodo de la clase que est´a implementado en las dos, llama al de la base. 1 p->f(); // llama a Base::f() Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 291 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 292. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Polimorfismo Nosotros queremos definir clases base que son gen´ericas (por ejemplo Matrix) y plantear algoritmos/operaciones gen´ericos para las mismas (por ejemplo GradConj()). Estos algoritmos toman un puntero a la clase base y llaman operaciones gen´ericas sobre la misma (por ejemplo el producto matriz vector MatVec()). Luego podemos definir clases derivadas para las matrices de distinto tipo (llena, banda, sparse, sim´etrica...) La idea es que cuando el algoritmo gen´erico GradConj() llama al m´etodo MatVec()), ´esta llamada sea despachada a la funci´on correspondiente en la clase derivada. Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 292 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 293. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Polimorfismo (cont.) Para que la llamada al m´etodo sea despachada a la clase derivada debemos declarar al m´etodo virtual en la clase base. 1 class Base { 2 public: 3 virtual void f(); 4 //. . . 5 6 class Derived : public Base { 7 public: 8 void f(); 9 //. . . 10 } 11 12 Derived d1, d2; 13 Base &b = d1; 14 b.f(); // llama a Derived::f() 15 16 Base *p = d2; 17 p->f(); // llama a Derived::f() Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 293 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 294. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Ejemplo polimorfismo. Integral 1D/2D/3D Queremos calcular la integral de funciones en segmentos ([a, b]) en 1D y productos cartesianos ([xa, xb] × [ya, yb]) en 2D y 3D. I1 = xb xa f(x) dx, I2 = yb ya xb xa f(x, y) dx dy, I3 = zb za yb ya xb xa f(x, y, z) dx dy dz, Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 294 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 295. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Ejemplo polimorfismo. Integral 1D/2D/3D (cont.) Empecemos definiendo el tipo de funciones de una variable 1 class scalarfun1d-t { 2 public: 3 virtual double eval(double x)=0; 4 }; Notemos que el m´etodo eval() est´a declarado =0 eso quiere decir que no se implementar´a, por lo tanto es una clase virtual pura es decir que no se pueden definir instancias de esta clase. S´olo es un prototipo del cual podremos derivar clases concretas que podr´an ser integradas. Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 295 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 296. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Ejemplo polimorfismo. Integral 1D/2D/3D (cont.) 1 // LIBRARY CODE 2 class scalarfun1d-t { 3 public: 4 virtual double eval(double x)=0; 5 }; 6 7 class integral1d-t { 8 public: 9 void set(int N, double a,double b,scalarfun1d-t *fxp); 10 double integral(); 11 }; 12 13 // USER CODE 14 class sin-fun-t : public scalarfun1d-t { 15 public: 16 double eval(double x) { return sin(x); } 17 } sin-fun; 18 19 int main() { 20 integral1d-t int1d; 21 int1d.set(100,0,1,&sin-fun); Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 296 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 297. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz 22 cout << "Integral of sin(x) in [0,1] is " 23 << int1d.integral() << endl; 24 return 0 25 } Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 297 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 298. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Clase que calcula integral 1D 1 class integral1d-t { 2 private: 3 int N; // Nbr of integration pts 4 double xa,xb; // integration interval 5 scalarfun1d-t *fp; // ptr to function 6 public: 7 // Ctor, set values 8 integral1d-t(int Na=0,double xaa=NAN, 9 double xba=NAN,scalarfun1d-t *fpa=NULL) { 10 set(Na,xaa,xba,fpa); 11 } 12 // Set values 13 void set(int Na,double xaa,double xba,scalarfun1d-t *fpa) { 14 N=Na; xa=xaa; xb=xba; fp=fpa; 15 } 16 // Computes the integral using Simpson’s rule 17 double integral() { 18 double 19 h = (xb-xa)/N, 20 h2 = h/2.0, Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 298 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 299. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz 21 finteg=0.0; 22 for (int j=0; j<N; j++) { 23 double x = j*h; 24 double f = fp->eval(x); 25 finteg += 2.0*f; 26 finteg += 4.0*fp->eval(x+h2); 27 } 28 finteg -= fp->eval(xa); 29 finteg += fp->eval(xb); 30 finteg *= h/6.0; 31 return finteg; 32 } 33 }; Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 299 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 300. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Integral 2D. Versi´on cruda La integral doble la hacemos como composici´on de dos integrales simples I2 = yb ya xb xa f(x, y) dx dy, = yb ya g(y) dy, g(y) = xb xa fy(x) dx. fx(y) ≡ f(x, y). x y xa xb ya yb y g(y) Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 300 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 301. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Integral 2D. Versi´on cruda (cont.) 1 class fy-t : public scalarfun1d-t { 2 public: 3 scalarfun2d-t *f2dp; // Ptr to 2var funct fx,y) 4 double y; 5 double eval(double x) { return f2dp->eval(x,y); } 6 } fy; 7 8 class g-t : public scalarfun1d-t { 9 public: 10 integral1d-t int1dx; // integral over x 11 double eval(double y) { // wrapper pass to calling class 12 fy.y = y; 13 return int1dx.integral(); 14 } 15 } g; 16 17 class integral2d-t { 18 private: 19 int N; // Nbr of integr segments 20 double xa,xb,ya,yb; // rectangle corners Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 301 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 302. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz 21 integral1d-t int1dy; // integral over y 22 public: 23 void set(int Na=0,double xaa=NAN,double xba=NAN, 24 double yaa=NAN,double yba=NAN, 25 scalarfun2d-t *f2dpa=NULL) { 26 N = Na; xa=xaa; xb=xba; ya=yaa; yb=yba; 27 fy.f2dp = f2dpa; 28 int1dy.set(N,ya,yb,&g); 29 g.int1dx.set(N,xa,xb,&fy); 30 } 31 integral2d-t(int Na=0, // Ctor 32 double xaa=NAN,double xba=NAN, 33 double yaa=NAN,double yba=NAN, 34 scalarfun2d-t *f2dpa=NULL) { 35 set(Na,xaa,xba,yaa,yba,f2dpa); 36 } 37 double integral() { 38 // 2D integral. Integrates over y the 39 // integral over x 40 return int1dy.integral(); 41 } 42 }; 43 Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 302 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 303. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz 44 // User code starts here---- 45 // Specific 2var function to be integrated 46 class fun-t : public scalarfun2d-t { 47 public: 48 double eval(double x,double y) { 49 // Must give (2/pi)ˆ2 = 0.40528 50 return sin(0.5*M-PI*x)*sin(0.5*M-PI*y); 51 } 52 } fun; 53 54 int main() { 55 int N=10; 56 57 // 2D integration example 58 integral2d-t int2d(N,0.0,1.0,0.0,1.0,&fun); 59 cout << "integral(x,y) = " << int2d.integral() << endl; 60 61 return 0; 62 } Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 303 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 304. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Integral 2D. Versi´on cruda (cont.) • fy y g son wrappers. • fy toma una scalarfun2d_t y devuelve una scalarfun1d_t fijando y a un valor (almacenado en el wrapper). • g es una scalarfun1d_t. Usa un objeto de la clase integradora 1D llamado int1dx. La funci´on eval correspondiente consiste en fijar el valor de y para la fy y llamar a la clase integradora sobre y. • Ambos objetos pertenecen a clases fy_t y g_t. • En esta implementaci´on hemos hecho estas clases globales y totalmente p´ublicas para simplificar. • La clase integradora 2D utiliza otr integrador 1D (int1dy) para integrar sobre y. • Las dos instancias de integral1d_t son utilizadas en forma recursiva, int1dy.eval() utiliza internamente a int1dx.eval() al evaluar la funci´on g(). Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 304 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 305. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Integral 2D. Versi´on cruda (cont.) 1 #include <cmath> 2 #include <iostream> 3 #include <vector> 4 using namespace std; 5 6 // One variable function ’f(x)’ 7 class scalarfun1d-t { 8 public: 9 virtual double eval(double x)=0; 10 }; 11 12 13 // Two variables function ’f(x,y)’ 14 class scalarfun2d-t { 15 public: 16 virtual double eval(double x,double y)=0; 17 }; 18 19 // Two variables function ’f(x,y,z)’ 20 class scalarfun3d-t { 21 public: 22 virtual double eval(double x,double y,double z)=0; Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 305 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 306. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz 23 }; 24 25 // Integral of a one var funct over an interval 26 class integral1d-t { 27 private: 28 int N; // Nbr of integration pts 29 double xa,xb; // integration interval 30 scalarfun1d-t *fp; // ptr to function 31 public: 32 // Ctor, set values 33 integral1d-t(int Na=0,double xaa=NAN, 34 double xba=NAN,scalarfun1d-t *fpa=NULL) { 35 set(Na,xaa,xba,fpa); 36 } 37 // Set values 38 void set(int Na,double xaa,double xba,scalarfun1d-t *fpa) { 39 N=Na; xa=xaa; xb=xba; fp=fpa; 40 } 41 // Computes the integral using Simpson’s rule 42 double integral() { 43 double 44 h = (xb-xa)/N, 45 h2 = h/2.0, Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 306 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 307. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz 46 finteg=0.0; 47 for (int j=0; j<N; j++) { 48 double x = j*h; 49 double f = fp->eval(x); 50 finteg += 2.0*f; 51 finteg += 4.0*fp->eval(x+h2); 52 } 53 finteg -= fp->eval(xa); 54 finteg += fp->eval(xb); 55 finteg *= h/6.0; 56 return finteg; 57 } 58 }; 59 60 61 // Integral of 2var functions over a rectangle 62 class integral2d-t { 63 private: 64 scalarfun2d-t *f2dp; // Ptr to 2var funct 65 integral1d-t int1dy, int1dx; // integrals over x and y 66 // For a given y gives the function fy(x) = f(x,y) 67 class fy-t : public scalarfun1d-t { 68 double y; Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 307 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 308. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz 69 integral2d-t *i2dp; // ptr to calling class 70 friend class integral2d-t; 71 public: 72 double eval(double x) { return i2dp->f2dp->eval(x,y); } 73 } fy; 74 // For a given y, integral over x: g(y) = int-{x=xa}ˆxb f(x,y) dx 75 class g-t : public scalarfun1d-t { 76 integral2d-t *i2dp; // ptr to calling class 77 friend class integral2d-t; 78 public: 79 double eval(double y) { // wrapper pass to calling class 80 return i2dp->geval(y); 81 } 82 } g; 83 double geval(double y) { 84 // Integrates over x for y=cnst 85 fy.y = y; 86 return int1dx.integral(); 87 } 88 int N; // Nbr of integr segments 89 double xa,xb,ya,yb; // rectangle corners 90 friend class fy-t; Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 308 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 309. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz 91 friend class g-t; 92 public: 93 void set(int Na=0,double xaa=NAN,double xba=NAN, 94 double yaa=NAN,double yba=NAN, 95 scalarfun2d-t *f2dpa=NULL) { 96 N = Na; xa=xaa; xb=xba; ya=yaa; yb=yba; 97 f2dp = f2dpa; 98 int1dy.set(N,ya,yb,&g); 99 int1dx.set(N,xa,xb,&fy); 100 } 101 integral2d-t(int Na=0, // Ctor 102 double xaa=NAN,double xba=NAN, 103 double yaa=NAN,double yba=NAN, 104 scalarfun2d-t *f2dpa=NULL) { 105 set(Na,xaa,xba,yaa,yba,f2dpa); 106 g.i2dp = this; 107 fy.i2dp = this; 108 } 109 double integral() { 110 // 2D integral. Integrates over y the 111 // integral over x 112 return int1dy.integral(); 113 } Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 309 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 310. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz 114 }; 115 116 117 // Integral of 3var functions over a cube 118 class integral3d-t { 119 private: 120 scalarfun3d-t *f3dp; // Ptr to 3var funct 121 integral2d-t int2dxy; // integral over x,y 122 integral1d-t int1dz; // integral over z 123 // For a given z gives the function fz(x,y) = f(x,y,z) 124 class fz-t : public scalarfun2d-t { 125 double z; 126 integral3d-t *i3dp; // ptr to calling class 127 friend class integral3d-t; 128 public: 129 double eval(double x,double y) { 130 return i3dp->f3dp->eval(x,y,z); 131 } 132 } fz; 133 // For a given z, gives g(z) = integral over x,y: 134 // g(z) = int-{x=xa}ˆxb int-{y=ya}ˆyb f(x,y,z) dx dy 135 class g-t : public scalarfun1d-t { 136 integral3d-t *i3dp; // ptr to calling class Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 310 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 311. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz 137 friend class integral3d-t; 138 public: 139 double eval(double z) { // wrapper pass to calling class 140 return i3dp->geval(z); 141 } 142 } g; 143 double geval(double z) { 144 // Integrates over x,y for z=cnst 145 fz.z = z; 146 return int2dxy.integral(); 147 } 148 int N; // Nbr of integr segments 149 double xa,xb,ya,yb,za,zb; // rectangle corners 150 friend class fz-t; 151 friend class g-t; 152 public: 153 void set(int Na,double xaa,double xba, // Set from args 154 double yaa,double yba, 155 double zaa,double zba, 156 scalarfun3d-t *f3dpa) { 157 N = Na; xa=xaa; xb=xba; ya=yaa; yb=yba; za=zaa; zb=zba; 158 f3dp = f3dpa; 159 int2dxy.set(N,xa,xb,ya,yb,&fz); Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 311 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 312. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz 160 int1dz.set(N,za,zb,&g); 161 } 162 integral3d-t(int Na=0, // Ctor 163 double xaa=NAN,double xba=NAN, 164 double yaa=NAN,double yba=NAN, 165 double zaa=NAN,double zba=NAN, 166 scalarfun3d-t *f3dpa=NULL) { 167 set(Na,xaa,xba,yaa,yba,zaa,zba,f3dpa); 168 g.i3dp = this; 169 fz.i3dp = this; 170 } 171 double integral() { // Comp 3D integral. Integrates over z 172 return int1dz.integral(); 173 } 174 }; 175 176 177 // User code starts here---- 178 // Specific 1var function to be integrated 179 class fun-t : public scalarfun1d-t { 180 public: 181 double eval(double x) { 182 // Must give (2/pi) = 0.63662 183 return sin(0.5*M-PI*x); Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 312 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 313. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz 184 } 185 } fun; 186 187 // Specific 2var function to be integrated 188 class fun2-t : public scalarfun2d-t { 189 public: 190 double eval(double x,double y) { 191 // Must give (2/pi)ˆ2 = 0.40528 192 return sin(0.5*M-PI*x)*sin(0.5*M-PI*y); 193 } 194 } fun2; 195 196 // Specific 3var function to be integrated 197 class fun3-t : public scalarfun3d-t { 198 public: 199 double eval(double x,double y,double z) { 200 // Must give (2/pi)ˆ3 = 0.25801 201 return sin(0.5*M-PI*x) 202 *sin(0.5*M-PI*y)*sin(0.5*M-PI*z); 203 } 204 } fun3; 205 206 int main() { 207 int N=10; Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 313 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 314. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz 208 // 1D integration example 209 integral1d-t int1d(N,0,1.0,&fun); 210 cout << "integral(x) = " << int1d.integral() << endl; 211 212 // 2D integration example 213 integral2d-t int2d(N,0.0,1.0,0.0,1.0,&fun2); 214 cout << "integral(x,y) = " << int2d.integral() << endl; 215 216 // 3D integration example 217 integral3d-t int3d(N,0.0,1.0,0.0,1.0,0.0,1.0,&fun3); 218 cout << "integral(x,y,z) = " << int3d.integral() << endl; 219 220 return 0; 221 } Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 314 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 315. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Integral 2D. Versi´on mejorada Funciona pero tiene algunas desprolijidades, usa variables globales y las clases auxiliares es mejor si se anidan en la clase que la utiliza integral2d_t. 1 class integral2d-t { 2 private: 3 scalarfun2d-t *f2dp; // Ptr to 2var funct 4 integral1d-t int1dy, int1dx; // integrals over x and y 5 // For a given y gives the function fy(x) = f(x,y) 6 class fy-t : public scalarfun1d-t { 7 double y; 8 integral2d-t *i2dp; // ptr to calling class 9 friend class integral2d-t; 10 public: 11 double eval(double x) { return i2dp->f2dp->eval(x,y); } 12 } fy; 13 // For a given y, integral over x: g(y) = int-{x=xa}ˆxb f(x,y) dx 14 class g-t : public scalarfun1d-t { 15 integral2d-t *i2dp; // ptr to calling class 16 friend class integral2d-t; Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 315 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 316. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz 17 public: 18 double eval(double y) { // wrapper pass to calling class 19 return i2dp->geval(y); 20 } 21 } g; 22 double geval(double y) { 23 // Integrates over x for y=cnst 24 fy.y = y; 25 return int1dx.integral(); 26 } 27 int N; // Nbr of integr segments 28 double xa,xb,ya,yb; // rectangle corners 29 friend class fy-t; 30 friend class g-t; 31 public: 32 void set(int Na=0,double xaa=NAN,double xba=NAN, 33 double yaa=NAN,double yba=NAN, 34 scalarfun2d-t *f2dpa=NULL) { 35 N = Na; xa=xaa; xb=xba; ya=yaa; yb=yba; 36 f2dp = f2dpa; 37 int1dy.set(N,ya,yb,&g); 38 int1dx.set(N,xa,xb,&fy); 39 } Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 316 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 317. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz 40 integral2d-t(int Na=0, // Ctor 41 double xaa=NAN,double xba=NAN, 42 double yaa=NAN,double yba=NAN, 43 scalarfun2d-t *f2dpa=NULL) { 44 set(Na,xaa,xba,yaa,yba,f2dpa); 45 g.i2dp = this; 46 fy.i2dp = this; 47 } 48 double integral() { 49 // 2D integral. Integrates over y the 50 // integral over x 51 return int1dy.integral(); 52 } 53 }; Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 317 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 318. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Integral 3D De la misma forma se puede hacer la integral en 3D combinando una integral en 1D con otra en 2D. 1 class integral3d-t { 2 private: 3 scalarfun3d-t *f3dp; // Ptr to 3var funct 4 integral2d-t int2dxy; // integral over x,y 5 integral1d-t int1dz; // integral over z 6 // For a given z gives the function fz(x,y) = f(x,y,z) 7 class fz-t : public scalarfun2d-t { 8 double z; 9 integral3d-t *i3dp; // ptr to calling class 10 friend class integral3d-t; 11 public: 12 double eval(double x,double y) { 13 return i3dp->f3dp->eval(x,y,z); 14 } 15 } fz; 16 // For a given z, gives g(z) = integral over x,y: Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 318 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 319. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz 17 // g(z) = int-{x=xa}ˆxb int-{y=ya}ˆyb f(x,y,z) dx dy 18 class g-t : public scalarfun1d-t { 19 integral3d-t *i3dp; // ptr to calling class 20 friend class integral3d-t; 21 public: 22 double eval(double z) { // wrapper pass to calling class 23 return i3dp->geval(z); 24 } 25 } g; 26 double geval(double z) { 27 // Integrates over x,y for z=cnst 28 fz.z = z; 29 return int2dxy.integral(); 30 } 31 int N; // Nbr of integr segments 32 double xa,xb,ya,yb,za,zb; // rectangle corners 33 friend class fz-t; 34 friend class g-t; 35 public: 36 void set(int Na,double xaa,double xba, // Set from args 37 double yaa,double yba, 38 double zaa,double zba, Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 319 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 320. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz 39 scalarfun3d-t *f3dpa) { 40 N = Na; xa=xaa; xb=xba; ya=yaa; yb=yba; za=zaa; zb=zba; 41 f3dp = f3dpa; 42 int2dxy.set(N,xa,xb,ya,yb,&fz); 43 int1dz.set(N,za,zb,&g); 44 } 45 integral3d-t(int Na=0, // Ctor 46 double xaa=NAN,double xba=NAN, 47 double yaa=NAN,double yba=NAN, 48 double zaa=NAN,double zba=NAN, 49 scalarfun3d-t *f3dpa=NULL) { 50 set(Na,xaa,xba,yaa,yba,zaa,zba,f3dpa); 51 g.i3dp = this; 52 fz.i3dp = this; 53 } 54 double integral() { // Comp 3D integral. Integrates over z 55 return int1dz.integral(); 56 } 57 }; Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 320 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 321. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Integral 1D/2D/3D. User code 1 class fun-t : public scalarfun1d-t { 2 public: 3 double eval(double x) { 4 // Must give (2/pi) = 0.63662 5 return sin(0.5*M-PI*x); 6 } 7 } fun; 8 9 // Specific 2var function to be integrated 10 class fun2-t : public scalarfun2d-t { 11 public: 12 double eval(double x,double y) { 13 // Must give (2/pi)ˆ2 = 0.40528 14 return sin(0.5*M-PI*x)*sin(0.5*M-PI*y); 15 } 16 } fun2; 17 18 // Specific 3var function to be integrated 19 class fun3-t : public scalarfun3d-t { 20 public: Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 321 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 322. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz 21 double eval(double x,double y,double z) { 22 // Must give (2/pi)ˆ3 = 0.25801 23 return sin(0.5*M-PI*x) 24 *sin(0.5*M-PI*y)*sin(0.5*M-PI*z); 25 } 26 } fun3; 27 28 int main() { 29 int N=10; 30 // 1D integration example 31 integral1d-t int1d(N,0,1.0,&fun); 32 cout << "integral(x) = " << int1d.integral() << endl; 33 34 // 2D integration example 35 integral2d-t int2d(N,0.0,1.0,0.0,1.0,&fun2); 36 cout << "integral(x,y) = " << int2d.integral() << endl; 37 38 // 3D integration example 39 integral3d-t int3d(N,0.0,1.0,0.0,1.0,0.0,1.0,&fun3); 40 cout << "integral(x,y,z) = " << int3d.integral() << endl; 41 42 return 0; 43 } Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 322 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 323. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Polimorfismo: ej. suma de los elementos de un vector Decargar vecsum.cpp 1 #include <cmath> 2 #include <iostream> 3 #include <vector> 4 using namespace std; 5 6 class vector-t { 7 public: 8 virtual int size()=0; 9 virtual double operator[ ](int j)=0; 10 }; 11 12 double vecsum(vector-t &v) { 13 int N = v.size(); 14 double sum = 0.0; 15 for (int j=0; j<N; j++) sum += v[j]; 16 return sum; 17 } 18 19 // A stride, linearly spaced values Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 323 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 324. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz 20 class stride-t : public vector-t { 21 private: 22 int N; 23 double start, inc; 24 public: 25 stride-t(int Na, double s,double i) : 26 N(Na), start(s), inc(i) { } 27 int size() { return N; } 28 double operator[ ](int j) { return start+j*inc; } 29 }; 30 31 // A wrapper to a vector<double> 32 class vecwrap-t : public vector-t { 33 private: 34 const vector<double> *ap; 35 public: 36 vecwrap-t(const vector<double> &a) : ap(&a) { } 37 int size() { return ap->size(); } 38 double operator[ ](int j) { return (*ap)[j]; } 39 }; 40 41 // A plain function that computes its values 42 class fun-t : public vector-t { 43 public: Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 324 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 325. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz 44 int N; 45 double p; 46 fun-t() : N(10), p(3.0) { } 47 int size() { return N; } 48 double operator[ ](int j) { return pow(j,p); } 49 }; 50 51 int main() { 52 stride-t stride(10,0,1); 53 cout << "sum(0. .9): " << vecsum(stride) << endl; 54 55 vector<double> a; 56 double p=3; int N=10; 57 a.resize(N); 58 for (int j=0; j<N; j++) a[j] = pow(j,p); 59 vecwrap-t vw(a); 60 cout << "sum-{j=0}ˆ{j=9} xˆ3 (with vecwrap): " 61 << vecsum(vw) << endl; 62 63 fun-t f; 64 cout << "sum-{j=0}ˆ{j=9} xˆ3 (with fun-t): " 65 << vecsum(f) << endl; 66 67 return 0; 68 } Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 325 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 326. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Contenedores de la librer´ıa STL Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 326 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 327. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz La clase vector • Inicialmente eran una serie de headers con clases desarrollado por Hewlett Packard. • Es una librer´ıa de contenedores (vectores, listas, conjuntos, maps...) y algoritmos (ordenamiento, filtrado, operaciones de conjuntos, eliminar elementos duplicados...) • Est´an templatizados es decir cada contenedor puede obtener objetos de un tipo arbitrario (todos del mismo), por ejemplo vector<int>, vector<double>. • Tambi´en puede contener objetos de clases definidas por el usuario vector<A>, a condici´on de que la clase A cumpla con ciertas restricciones (por ejemplo tener un constructor por defecto, operador de asignaci´on a1=a2...) • Muchos pueden anidarse, por ejemplo vector<vector<int>>. • Algunos pueden involucrar m´as de un tipo, por ejemplo map<int,string>. Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 327 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 328. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz La clase vector • Emula el comportamiento de un vector est´andar de C, pero se puede redimensionar din´amicamente y libera sus recursos din´amicamente. 1 vector<int> v; // declara el vector 2 v.resize(N); // lo dimensiona a N elementos 3 // OJO preserva elementos existentes. 4 vector<int> v(N); // Lo crea con N elementos 5 int z; vector<int> v(N,z); // Lo crea con N elementos =z 6 v.clear(); // Elimina todos los elementos dejando al vector vac´ıo • Tiene sobrecargado el operator[] para acceder para lectura/escritura los elementos del vector. El acceso es en tiempo O(1). 1 x = v[j]; v[k]=z; • v.push_back(z) inserta el elemento z al final (muy eficiente, O(1) amortizado). • z = v.front(), z = v.back() accede al primer y ´ultimo elemento del vector (eficiente, O(1). • Se puede acceder a los elementos a trav´es de iterators 1 // Comienzo del vector (v[0]) 2 vector<int>::iterator q= v.begin(); Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 328 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 329. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz 3 int z = *q; // Se dereferencian como ptrs 4 q++; // Incrementa al siguiente elemento *q equivale a v[0]. Despu´es de hacer el incremento equivale a v[1]. • La clase iterator es una clase anidada dentro de vector. Casi todos los contenedores tienen su propia clase iterator. • El iterator v.end() es un iterator pasado el ´ultimo elemento del vector 1 vector<int> v(10); 2 vector<int>::iterator q = v.end(); 3 // ERROR: q is not dereferenciable 4 cout << "Last element is " << *q << endl; q apunta a v[10] (el ´ultimo elemento es v[9]). • Se puede iterar sobre todo el vector as´ı 1 // Suma todos los elementos de v 2 double sum = 0; 3 vector<int>::iterator q = v.begin(); 4 while (q!=v.end()) { 5 sum += *q; 6 q++; 7 } • Notar que q++ se puede hacer ya que el operator++ est´a sobrecargado para la clase iterator. Igual que para enteros existe la versi´on prefija y postfija. Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 329 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 330. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz • Para vector tambi´en se puede iterar como con un vector com´un 1 double sum = 0; 2 for (int j=0; j<v.size(); j++) sum += v[j]; Pero esto se puede usar s´olo con vector, con iteradores se puede iterar sobre casi cualquiera de los otros contenedores. • Los iterators de vector<> soportan aritm´etica de punteros. Esto es s´olo v´alido para los iterators de vector, no para list<> o map<> por ejemplo. • Se puede insertar un elemento en cualquier posici´on del vector, sin embargo esto puede ser costoso (O(n)). 1 vector<double> v(100,0); 2 q = v.begin() + 50; // Apunta al elemento v[50] 3 v.insert(q,33); // Inserta un 33 en la posici´on 50 Despu´es de esto el vector tiene 101 elementos. Por supuesto esto implica no solo redimensionar el vector sino tambi´en copiar los elementos en [50,99] a [51,100]. • Para pasar los vectores como argumentos conviene hacerlo a trav´es de referencias para evitar la copia. Para indicar que la funci´on no modifica al vector se debe declarar el argumento como const. 1 double vecsum(const vector<double> &w) • Pero entonces se debe iterar sobre el mismo con un const_iterator Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 330 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 331. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz 1 double vecsum(const vector<double> &w) { 2 double sum = 0.0; 3 vector<double>::const-iterator q = w.begin(); 4 while (q!=w.end()) sum += *q++ 5 return sum; 6 } • Como es declarado un const_iterator no se le puede asignar un valor 1 vector<double>::const-iterator q; 2 //. . . . 3 *q = z; // error! • Como muchos otros contenedores de las STL, permite hacer un swap con otro contenedor 1 vector<double> v,w; 2 // Llena v y w . . . 3 v.swap(w); Equivale a 1 vector<double> v,w, tmp; 2 // Llena v y w . . . 3 tmp = v; 4 v = w; 5 w = tmp; Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 331 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 332. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Pero sin hacer copias ni duplicados, o sea es muy eficiente. • Tambi´en se puede borrar elementos o un rango de elementos 1 w.erase(q); // Elimina el elemento en q (ineficiente) 2 w.erase(p,q); // Elimina todo el rango [p,q) (ineficiente) 3 w.pop-back(); // Elimina el ultimo elemento (eficiente) • En toda la documentaci´on (y en general en ciencias de la computaci´on) se utilizan rangos cerrado/abierto [p,q) que quiere decir todos los elementos desde p a q incluyendo a p pero sin incluir a q. • vector<> como casi todos los otros contenedores soportan asignaci´on: operator= (deep copy), operator==, (comparaci´on por igualdad y distinto). • Para usarlo 1 #include <vector> 2 using namespace std; • Como casi todos los otros contenedores tiene bool v.isempty() (retorna verdadero si el contenedor est´a vac´ıo). Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 332 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 333. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Algoritmos in-place • Cuando se escriben c´odigos que manipulan contenedores muy grandes (en tama˜no de memoria requerida) es importante saber cuanta memoria adicional se requiere para realizar la operaci´on. • Si el contenedor es de longitud n y la cantidad de memoria requerida es O(1) es decir no crece con el tama˜no del contenedor se dice que el algoritmo es in-place. • Por ejemplo si queremos intercambiar los contenidos de dos vectores x e y podemos utilizar las siguientes opciones 1 // VERSION 1 (in-place) 2 for (int j=0; j<N; j++){ 3 double aux=x[j]; 4 x[j]=y[j]; 5 y[j]=aux; 6 } 7 8 // VERSION 2 (NOT in-place) 9 vd-t aux=x; 10 x=y; y=aux; 11 12 // VERSION 3: Uses C++ vector<> builtin swap Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 333 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 334. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz 13 x.swap(y); 14 15 // VERSION 4: Uses generic STL swap 16 #include <algorithm> 17 swap(x,y); • La versi´on 1 es in-place, ya que si bien requiere de memoria adicional (el int j y double aux), son 12 bytes y no crece con el tama˜no del vector N. • En cambio para la versi´on 2, SI requiere de el vector aux que es de tama˜no N, por lo tanto NO es in-place. • La versi´on 3, utiliza el swap() builtin de la clase vector<> y SI es in-place de acuerdo a lo que dice la documentaci´on. Da lo mismo hacer x.swap(y) o y.swap(x). • La versi´on 4 utiliza el algoritmo gen´erico de las STL que funciona para casi cualquier contenedor pero que no est´a optimizado, por lo tanto puede ser que en la pr´actica sea equivalente a la versi´on 1. Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 334 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 335. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz La clase list • El contenedor lista (list<>) es (como vector<>) un contenedor lineal es decir los elementos en la lista se pueden asociar con una posici´on entera. Sin embargo no se puede acceder a la posici´on m de la lista en forma eficiente (es decir O(1)) ya que los elementos est´an almacenados en celdas enlazadas. 1 list<double> L; 2 // pone elementos en L. . . 3 double z = L[m]; // NO, [ ] s´olo para vectores 4 double z; • S´olo se puede acceder al elemento m-´esimo haciendo un lazo. 1 double z; 2 list<double>::iterator q = L.begin(); 3 for (int j=0; j<m; j++) q++; 4 z = *q; // Accede al elemento m • La lista es doblemente enlazada es decir que se puede avanzar en las dos direcciones (q++ y q--) eficientemente (O(1)). • Existe otra clase slist<> que es simplemente enlazada, por lo tanto q++ es O(1), mientras que q-- es O(n) (debe ir al principio y recorrer la lista Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 335 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 336. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz hasta encontrar la celda que apunta a q). • El inter´es de list<> es que permite insertar en cualquier posici´on muy eficientemente (O(1)) 1 list<double> L; 2 // Pone elementos en L. . . 3 // q apunta a cualquier posici´on en L 4 q = L.insert(q,w); // Inserta un nuevo elemento en 5 // el medio de la lista • insert retorna la posici´on “refrescada” q. 1 L.insert(q,w); // deja q invalido 2 z = *q; // posible error en tiempo de ejecuci´on 3 4 q = L.insert(q,w); // OK refrezca q 5 z = *q; // OK! • Para borrar un elemento q = L.erase(q);, tambi´en se debe refrescar el iterator. 1 list<int>::iterator q = L.begin(); 2 while (q!=L.end()) q = L.erase(q); Equivale a L.clear(), elimina todos los elementos de a uno por el frente. • Tambi´en se puede pasar todo un rango de una lista a otra 1 list<int> L1,L2; Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 336 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 337. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz 2 // Pone elementos en L1, y L2 3 L1.splice(r,L2,p,q)); inserta todo el rango [p,q) de L2 en la posici´on r de L1. MUY EFICIENTE (O(1)). • list<> tambi´en tiene swap. De hecho swap se puede implementar para list en t´erminos de splice 1 list<int> L1,L2,tmp; 2 // Pone elementos en L1, y L2 3 tmp.splice(tmp.begin(),L1.begin(),L1.end()); 4 L1.splice(L1.begin(),L2.begin(),L2.end()); 5 L2.splice(L2.begin(),tmp.begin(),tmp.end()); Toda la operaci´on es O(1), por lo tanto es tan eficiente como swap. Pero splice() es m´as general (es como swap pero para pedazos de lista). • vector no tiene splice(). • Los headers son #include <list> y <slist> Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 337 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 338. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz La clase set • Los conjuntos son contenedores que almacenan elementos diferentes entre s´ı. 1 set<int> S; 2 for (int j=0; j<10; j++) S.insert(j); 3 S.insert(5); // No hace nada (5 ya estaba) • El m´etodo find(x) retorna la posici´on donde se encuentra un elemento dado x, si el elemento no est´a retorna S.end() 1 set<int>::iterator q = S.find(x); 2 if (q!=S.end()) { 3 // x est´a en S y *q==x 4 } • find() es muy eficiente (O(log n)). Esta es la condici´on de dise˜no de set. • Si se declara un set<A> entonces la clase A tiene que tener los requisitos de antes (ctor por defecto, operador de asignaci´on). Pero adem´as debe tener sobrecargado el operator<. Esto es as´ı ya que el find() es eficiente porque guarda los elementos ordenados. Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 338 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 339. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz • Se puede recorrer los elementos con un iterador, est´an ordenados por operator< 1 set<int>::iterator q = S.begin(); 2 while (q!=S.end()) cout << *q++ << " "; 3 cout << endl; Imprime todos los elementos ordenados por operator< • El header correspondiente es <set> • Notar que insert() no toma un iterator (como en list vector). En set no se inserta en una posici´on en particular, ya que el mismo contenedor mantiene los elementos en un cierto orden. • Hay dos sabores de erase 1 S.erase(q); // Erase de un iterator (debe ser dereferenciable) 2 int z = S.erase(x); // erase de un elemento El primero toma un iterator que debe ser dereferenciable, elimina el elemento correspondiente y no retorna nada. El segundo toma un elemento x y se fija si est´a o no en el conjunto. Si est´a lo elimina del conjunto y si no, no hace nada. En ambos casos el valor de retorno es el n´umero de elementos efectivamente eliminados, es decir 1 o 0. Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 339 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 340. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz • Operaciones binarias de conjuntos: C = A ∩ B 1 set-intersection(a.begin(),a.end(),b.begin(),b.end(), 2 inserter(c,c.begin())); • Se pueden utilizar las funciones que realizan las operaciones binarias. Est´an en el header <algorithm>. No son m´etodos de la clase, son funciones friend. • C = A ∪ B 1 C.clear(); 2 set-union(A.begin(),A.end(),B.begin(),B.end(), 3 inserter(C,C.begin())); • C = A − B 1 set-difference(a.begin(),a.end(),b.begin(),b.end(), 2 inserter(c,c.begin())); • Notar que en principio opera sobre un rango en A y otro en B e inserta la uni´on de los mismos (sin elementos duplicados) en C. De la forma en que est´a llamada arriba hace la operaci´on est´andar de uni´on. • C = A − B 1 C.clear(); Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 340 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 341. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz 2 set-difference(A.begin(),A.end(),B.begin(),B.end(), 3 inserter(C,C.begin())); • C = A ∩ B 1 C.clear(); 2 set-intersection(A.begin(),A.end(),B.begin(),B.end(), 3 inserter(C,C.begin())); • Las operaciones binarias son muy eficientes O(n log n). Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 341 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 342. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz La clase map • Representa una correspondencia entre claves de un conjunto dominio y un conjunto imagen o contradominio. Como si fuera una base de datos almacena pares (clave,valor) ordenados por la clave y despu´es se puede buscar las asignaciones por la clave. • Ejemplo, sueldos de los empleados 1 map<int,double> sueldos; 2 sueldos[13234567] = 23000.34; 3 sueldos[30245654] = 18356.34; 4 . . . . 5 int dni = 34567234; 6 if (sueldos.find(dni)==sueldos.end()) { 7 // Este empleado no tiene asignado un sueldo en la tabla. . . 8 } else { 9 cout << "el sueldo correspondiente es " << sueldos[dni] << endl; 10 } • El nombre utilizado para los tipos es key_t para el dominio, range_t. En el ejemplo anterior key_t es int y range_t es double. • Cuando se itera sobre el map con el lazo t´ıpico 1 map<int,double>::iterator q = sueldos.begin(); Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 342 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 343. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz 2 while (q!=sueldos.end()) { 3 cout << "DNI " << q->first << ", sueldo " << q->second << endl; 4 q++; 5 } • Notar que los iteradores iteran sobre los pares clave, valor, de hecho son estruturas de tipo pair<int,double>. • El contenedor pair es el m´as b´asico de las STL y permite agrupar dos elementos de tipo diferente o igual: pair<int,int> dos ints, pair<int,string>.... • Los campos de pair se acceden por los miembros first y second. 1 pair<int,double> p; 2 p.first = 23; 3 p.second = 234.56; • Tambi´en se puede declarar pair<int,double> p(23,45.67); • El map tiene un efecto colateral no com´un que es que si indexamos por una clave que no tiene asignado un valor entonces crea una asginaci´on poniendo como imagen el constructor por defecto de range_t 1 map<int,string> M; 2 string z = M[5]; // Asigna z= string vacio !!! • El tipo key_t tiene los mismos requerimientos que para un set es decir: Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 343 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 344. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz constructor por defecto y por copia, operador de asignaci´on, operator<. Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 344 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 345. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Algoritmos • Permiten operar sobre los diferentes contenedores. Muchas veces en forma transparente, el mismo algoritmo se puede aplicar a diferentes contenedores. • Tal vez el m´as paradigm´atico y util es sort 1 vector<double> v; 2 // Pone elementos en v. . . 3 // Ordena por valor absoluto 4 sort(v.begin(),v.end()); sort(p,q) ordena los elementos en el rango [p,q). Notar que no se le pasa el contenedor, solo dos iteradores. • Si hay que ordenar todo el contenedor hay que pasar v.begin(), v.end() • Se puede utilizar tambi´en para listas • Para conjuntos no tiene sentido, ya est´an internamente ordenados. • Para clases (vector<A>) ordena por operator< por lo tanto debe estar sobrecargado. • Si se quiere ordenar por otro criterio y no se puede modificar el operator< se puede pasar una funci´on de comparaci´on: 1 // Funcion de comparacion por valor absoluto Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 345 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 346. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz 2 bool comp(int x,int y) { return abs(x)<abs(y); } 3 vector<int> v; 4 // Pone elementos en v. . . 5 sort(v.begin(),v.end(),comp); • Es MUY r´apido, O(n log n). Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 346 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 347. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Programaci´on funcional • Podemos escribir algoritmos que modifican los valores de un vector (u otro contenedor), por ejemplo sumarle a todos los valores contenidos en un ´arbol un valor, o duplicarlos. 1 void vecsum(vector<int> &v,int w) { 2 for (int j=0; j<w.size(); j++) v[j] += w; 3 } 4 5 void vecscale(vector<int> &v,int w) { 6 for (int j=0; j<w.size(); j++) v[j] *= w; 7 } • Todos estos son casos particulares de un algoritmo m´as general apply(v,f) que tiene como argumentos un vector v y una “funci´on escalar” T f(T) (donde T es el tipo del vector). y le aplica a cada uno de los valores nodales la funci´on en cuesti´on. Este es un ejemplo de “programaci´on funcional”, es decir, programaci´on en los cuales los datos de los algoritmos pueden ser tambi´en funciones. Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 347 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 348. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Programaci´on funcional (cont.) • C++ tiene soporte para la programaci´on funcional pasando “punteros a funciones”. Tambi´en se puede usar “functors”, clases que sobrecargan el operador (). • Lenguajes funcionales puros: Lisp/Scheme, ML, Haskell... las funciones son “objetos de primera clase”. • Soluci´on funcional: 1 void apply(vector<int>&v,int (*f)(int)) { 2 int N = v.size(); 3 for (int j=0; j<N; j++) v[j] = f(v[j]); 4 } 5 6 int sum10(int x) { return x+10; } 7 8 int scale10(int x) { return x*10; } 9 10 int main() { 11 int N=10; 12 vector<int> v(N); 13 for (int j=0; j<N; j++) v[j] = j; 14 dump(v,"v antes"); 15 apply(v,sum10); Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 348 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 349. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz 16 dump(v,"v += 10"); 17 apply(v,scale10); 18 dump(v,"v *= 10"); 19 return 0; 20 } Da lo siguiente: 1 [mstorti@galileo sources]$$ ./functional.bin 2 v antes: 0 1 2 3 4 5 6 7 8 9 3 v += 10: 10 11 12 13 14 15 16 17 18 19 4 v *= 10: 100 110 120 130 140 150 160 170 180 190 5 [mstorti@galileo sources]$$ Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 349 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 350. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Programaci´on funcional (cont.) • Se pasa el puntero a la funci´on. • La “signatura” es int f(int). La declaraci´on de punteros a tales funciones se hace reemplazando en la signatura el nombre de la funci´on por (*) es decir int (*)(int). • Dentro de esta funci´on auxiliar el puntero a funci´on f se aplica como una funci´on normal. Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 350 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 351. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Programaci´on funcional (cont.) Soluci´on funcional con clases y polimorfismo 1 class map-t { 2 public: 3 virtual int f(int)=0; 4 }; 5 6 void apply(vector<int>&v,map-t &m) { 7 int N = v.size(); 8 for (int j=0; j<N; j++) v[j] = m.f(v[j]); 9 } 10 11 class sum-t : public map-t { 12 public: 13 int w; 14 int f(int x) { return x+w; } 15 } sum; 16 17 class scale-t : public map-t { 18 public: 19 int w; 20 int f(int x) { return x*w; } Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 351 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 352. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz 21 } scale; 22 23 int main() { 24 int N=10; 25 vector<int> v(N); 26 for (int j=0; j<N; j++) v[j] = j; 27 dump(v,"v antes"); 28 sum.w = 10; 29 apply(v,sum); 30 dump(v,"v += 10"); 31 32 sum.w = 30; 33 apply(v,sum); 34 dump(v,"v += 30"); 35 36 scale.w = 10; 37 apply(v,scale); 38 dump(v,"v *= 10"); 39 40 scale.w = 2; 41 apply(v,scale); 42 dump(v,"v *= 2"); 43 44 return 0; 45 } Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 352 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 353. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Da lo siguiente: 1 [mstorti@galileo sources]$ ./functional2.bin 2 v antes: 0 1 2 3 4 5 6 7 8 9 3 v += 10: 10 11 12 13 14 15 16 17 18 19 4 v += 30: 40 41 42 43 44 45 46 47 48 49 5 v *= 10: 400 410 420 430 440 450 460 470 480 490 6 v *= 2: 800 820 840 860 880 900 920 940 960 980 7 [mstorti@galileo sources]$ Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 353 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 354. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Otro ejemplo de progr. fun. Reducci´on • reduce(v,g,null) que toma como argumentos un vector v y una funci´on asociativa int g(int,int) (por ejemplo la suma, el producto, el m´aximo o el m´ınimo) y devuelve el resultado de aplicar la funci´on asociativa a todos los valores nodales, hasta llegar a un ´unico valor. • null es el valor nulo para esa funci´on asociativa, es decir g(x,null)=x para cualquier x. Para g=+ es null=0, ya que es siempre x+0=0 Para g=* es null=1, ya que es siempre x*1=x Para g=max es null=-Inf, ya que es siempre max(x,-Inf)=x Para g=min es null=+Inf, ya que es siempre min(x,+Inf)=x Para g=|| es null=false, ya que es siempre x||false=x Para g=&& es null=true, ya que es siempre x||true=x 1 void filter-odd(vector<int> &v) { 2 vector<int> tmp; 3 int N=v.size(); 4 for (int j=0; j<N; j++) 5 if (v[j]%2==0) tmp.push-back(v[j]); Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 354 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 355. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz 6 v = tmp; 7 } 8 9 typedef bool (*pred-t)(int); 10 11 void filter(vector<int> &v,pred-t p) { 12 vector<int> tmp; 13 int N=v.size(); 14 for (int j=0; j<N; j++) if (p(v[j])) tmp.push-back(v[j]); 15 v = tmp; 16 } 17 18 bool even(int x) { return x%2==0; } 19 20 bool positive(int x) { return x>0; } 21 22 int main() { 23 int N=10; 24 vector<int> v(N),vcpy; 25 for (int j=0; j<N; j++) v[j] = j; 26 vcpy = v; 27 28 dump(v,"v antes"); 29 filter-odd(v); 30 dump(v,"even(v)"); 31 32 v.resize(N); Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 355 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 356. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz 33 for (int j=0; j<N; j++) v[j] = j-N/2; 34 35 dump(v,"v antes"); 36 filter(v,positive); 37 dump(v,"positive(v) "); 38 39 return 0; 40 } Da: 1 [mstorti@galileo sources]$ ./reduce.bin 2 v antes: 0 1 2 3 4 5 6 7 8 9 3 sum(v): 45 4 max(v): 9 5 min(v): 0 6 [mstorti@galileo sources]$ Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 356 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 357. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Prog funcional. Filtros • Otra aplicaci´on pueden ser “filtros”, como la funci´on filter_odd, elimina los elementos impares. • Podr´ıamos escribir una funci´on remove_if(v,pred) que tiene como argumentos un vector v y una funci´on predicado bool pred(T). La funci´on remove_if elimina todos los elementos x para cuyos valores la funci´on pred(*n) retorna verdadero. La funci´on filter_odd se podr´ıa obtener entonces simplemente pasando a remove_if una funci´on predicado que retorna verdadero si el argumento es impar. Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 357 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 358. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Versi´on funcional 1 void filter-odd(vector<int> &v) { 2 vector<int> tmp; 3 int N=v.size(); 4 for (int j=0; j<N; j++) 5 if (v[j]%2==0) tmp.push-back(v[j]); 6 v = tmp; 7 } 8 9 typedef bool (*pred-t)(int); 10 11 void filter(vector<int> &v,pred-t p) { 12 vector<int> tmp; 13 int N=v.size(); 14 for (int j=0; j<N; j++) if (p(v[j])) tmp.push-back(v[j]); 15 v = tmp; 16 } 17 18 bool even(int x) { return x%2==0; } 19 20 bool positive(int x) { return x>0; } 21 22 int main() { Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 358 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 359. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz 23 int N=10; 24 vector<int> v(N),vcpy; 25 for (int j=0; j<N; j++) v[j] = j; 26 vcpy = v; 27 28 dump(v,"v antes"); 29 filter-odd(v); 30 dump(v,"even(v)"); 31 32 v.resize(N); 33 for (int j=0; j<N; j++) v[j] = j-N/2; 34 35 dump(v,"v antes"); 36 filter(v,positive); 37 dump(v,"positive(v) "); 38 39 return 0; 40 } Da: 1 [mstorti@galileo sources]$ ./filter.bin 2 v antes: 0 1 2 3 4 5 6 7 8 9 3 even(v): 0 2 4 6 8 4 v antes: -5 -4 -3 -2 -1 0 1 2 3 4 5 positive(v) : 1 2 3 4 6 [mstorti@galileo sources]$ Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 359 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 360. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz Versi´on funcional con clases 1 class pred-t { 2 public: 3 virtual bool f(int)=0; 4 }; 5 6 void remove-if(vector<int>&v,pred-t &p) { 7 vector<int> tmp; 8 int N = v.size(); 9 for (int j=0; j<N; j++) if(p.f(v[j])) tmp.push-back(v[j]); 10 v = tmp; 11 } 12 13 class even-t : public pred-t { 14 public: 15 bool f(int x) { return x%2==0; } 16 } even; 17 18 class positive-t : public pred-t { 19 public: 20 bool f(int x) { return x>0; } 21 } positive; Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 360 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))
  • 361. Programaci´on en C++ para Ciencia e Ingenier´ıa, por M.Storti, L. Dalc´ın, Rodrigo Paz 22 23 int main() { 24 int N=10; 25 vector<int> v(N),vcpy; 26 for (int j=0; j<N; j++) v[j] = j-N/2; 27 vcpy = v; 28 29 dump(v,"v antes"); 30 remove-if(v,even); 31 dump(v,"even(v)"); 32 33 v = vcpy; 34 dump(v,"v antes"); 35 remove-if(v,positive); 36 dump(v,"positive(v) "); 37 38 return 0; 39 } Da: 1 [mstorti@galileo sources]$ ./filter2.bin 2 v antes: -5 -4 -3 -2 -1 0 1 2 3 4 3 even(v): -4 -2 0 2 4 4 v antes: -5 -4 -3 -2 -1 0 1 2 3 4 5 positive(v) : 1 2 3 4 6 [mstorti@galileo sources]$ Facultad de Ingenier´ıa y Ciencias H´ıdricas FICH - UNL slide 361 ((version texstuff-1.2.9-12-ge83ced6) (date Wed May 27 12:15:38 2015 -0300) (processed-date Wed May 27 12:45:10 2015 -0300))