You are on page 1of 342

Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L.

Dalcn, Rodrigo Paz

Programacion en C++ para Ciencia e


Ingeniera
Mario Storti, Lisandro Dalcn, Rodrigo Paz
http://www.cimec.org.ar/prog

Facultad de Ingeniera y Ciencias Hdricas


Universidad Nacional del Litoral http://www.unl.edu.ar

Centro de Investigacion de Metodos Computacionales - CIMEC


INTEC, (CONICET-UNL), http://www.cimec.org.ar

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 1


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Autores

Mario Storti <mario.storti@gmail.>


Lisandro Dalcn, <dalcinl@gmail.com>
Rodrigo Paz, <rodrigo.r.paz@gmail.com>

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 2


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Contents

slide 11.....Elementos basicos de programacion


. slide 12.....Compilacion vs. interpretes
. slide 13.....El proceso de compilacion
. slide 15.....El preprocesador CPP
. slide 18.....Chequeo de tipos
. slide 19.....Compilacion por separado
. slide 21.....Declaraciones y definiciones
. slide 23.....Definiciones y declaraciones de variables
. slide 25.....Incluyendo headers
. slide 28.....Usando libreras
. slide 29.....Formato de include para C++
. slide 30.....Un primer programa en C++
. slide 31.....Namespaces
. slide 34.....Estructura de un programa
. slide 36.....Hello world
. slide 37.....Concatenacion de arreglos de caracters
. slide 38.....Entrada de datos
. slide 39.....Llamando a otros programas
Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 3
((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

. slide 40.....Strings de C
. slide 41.....Strings de C++
. slide 43.....Escribir y leer de archivos
. slide 45.....La clase vector
. slide 48.....Ejercicios
slide 49.....El C en C++
. slide 50.....Funciones
. slide 51.....Valores de retorno
. slide 53.....Usando la librera estandar de C
. slide 54.....Control de ejecucion. True and False
. slide 56.....If-else
. slide 60.....while
. slide 63.....do-while
. slide 64.....Lazo for
. slide 66.....Break and continue
. slide 67.....La sentencia switch
. slide 69.....goto
. slide 71.....Recursion
. slide 73.....Operadores
. slide 74.....Operadores de auto incremento
. slide 76.....Tipos de datos
Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 4
((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

. slide 79.....Especificadores
. slide 82.....Punteros
. slide 92.....Referencias
. slide 95.....Punteros a void
. slide 97.....Scope de las variables
. slide 99.....Definiendo variables on-the-fly
. slide 103.....Variables locales
. slide 107.....Punteros a variables locales
. slide 108.....Variables estaticas
. slide 110.....Constantes
. slide 111.....Operadores. Asignacion
. slide 112.....Operadores matematicos
. slide 113.....Operadores relacionales
. slide 114.....Operadores logicos
. slide 115.....El operador hook
. slide 116.....Errores comunes con los operadores
. slide 117.....Operadores de cast
. slide 118.....Operador sizeof
. slide 119.....typedef: Aliases de tipos
. slide 120.....Estructuras
. slide 124.....Arrow operator
Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 5
((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

. slide 125.....Enums
. slide 128.....Arreglos de estructuras
. slide 129.....Punteros y arreglos
. slide 131.....Arreglos de punteros
. slide 135.....Aritmetica de punteros
. slide 137.....Tamanos de estructuras
slide 138.....Programacion Orientada a Objetos
. slide 139.....Abstraccion de datos
. slide 149.....POO basica
. slide 159.....Inclusion de headers
. slide 163.....Estructuras enlazadas
. slide 171.....Mas sobre scoping
. slide 172.....Tipos Abstractos de Datos (ADT)
. slide 173.....Ocultando la implementacion
. slide 175.....Control de acceso a los miembros
. slide 179.....Amistad (Friendship)
. slide 182.....Anidamiento (nesting) y amistad
. slide 183.....Object layout
. slide 184.....Clases
. slide 188.....Ocultando totalmente la implementacion
. slide 190.....Inicializacion y cleanup
Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 6
((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

. slide 192.....El constructor


. slide 193.....El destructor
. slide 196.....Eliminacion del bloque de definicion
. slide 198.....Clase stash con ctor/dtor
. slide 202.....Stack con ctor/dtor
. slide 205.....Initializacion de agregados
. slide 206.....Inicializacion de estructuras
. slide 207.....Sobrecarga de funciones
. slide 211.....Argumentos por default
. slide 212.....Constantes
. slide 215.....Punteros a arreglos constantes de caracteres
. slide 216.....Const en argumentos de funciones
. slide 217.....Const en clases
. slide 218.....Objetos const y funciones de la clase
slide 220.....Chapter 5
. slide 221.....Funciones inline
. slide 225.....Especificaciones de linkedicion
. slide 227.....Referencias en C++
. slide 233.....Reglas para las referencias
. slide 235.....Paso por referencia y por copia
. slide 236.....El constructor por copia
Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 7
((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

. slide 237.....Sobrecarga de operadores


. slide 242.....Sobrecarga de operadores unarios
. slide 250.....Sobrecarga de operadores binarios
slide 272.....Chapter
. slide 273.....Otros operadores que se pueden sobrecargar
. slide 274.....Creacion dinamica de objetos
. slide 275.....Uso de la memoria dinamica en C
. slide 276.....Uso de la memoria dinamica en C++
. slide 278.....Porque usar new y no arreglos
. slide 279.....Memory exhaust
. slide 280.....Composicion
. slide 282.....Composicion y la cadena de inicializacion
. slide 283.....Herencia
. slide 286.....Redefinicion de metodos
. slide 288.....Herencia protegida
. slide 290.....Upcasting
. slide 291.....Polimorfismo
. slide 293.....Ejemplo polimorfismo. Integral 1D/2D/3D
. slide 297.....Clase que calcula integral 1D
. slide 299.....Integral 2D. Version cruda
. slide 314.....Integral 2D. Version mejorada
Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 8
((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

. slide 317.....Integral 3D
. slide 320.....Integral 1D/2D/3D. User code
. slide 322.....Polimorfismo: ej. suma de los elementos de un vector
. slide ??.....Ejemplo clase vector sparse
slide 325.....Contenedores de la librera STL
. slide 327.....La librera STL
. slide 327.....La clase vector
. slide 332.....La clase list
. slide 335.....La clase set
. slide 339.....La clase map
. slide 341.....Algoritmos

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 9


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Dictado

Docentes de la catedra:
. Mario Storti <mario.storti@gmail.>
. Lisandro Dalcn, <dalcinl@gmail.com>
. Rodrigo Paz, <rodrigo.r.paz@gmail.com>

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 10


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Elementos basicos de
programacion

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 11


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Compilacion vs. interpretes

Algunos lenguajes de programacion tienen un interprete, por ejemplo


Matlab/Octave, Python, Perl, Lisp/Scheme. En un interprete el usuario va
emitiendo comandos que son interpretados por el interprete y va
devolviendo un resultado.
Por contraposicion, los lenguajes compilados el usuario escribe un
archivo con lneas de codigo, el cual es procesado por un compilador, que
genera codigo de maquina, el cual es ejecutado directamente por el
procesador.
Ventajas de la compilacion: el codigo suele ser mas rapido, y mas
compacto.
Desventajas: el paso de codigo a ejecutarlo es inmediato, no hay pasos
intermedios. Usualmente los interpretes permiten escribir tareas que se
repiten comunmente en archivos de texto (scripts). El usuario puede
ademas mezclar estas funciones con comandos directamente en el
interprete. Tambien con los interprete es mas facil debuggear.
C++ es un lenguaje compilado.

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 12


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

El proceso de compilacion

El caso mas simple es cuando todo el codigo del programa esta en un


solo 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 codigo de maquina. (No tiene
relacion con la Programacion Orientada a Objetos).

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 13


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

El proceso de compilacion (cont.)

Si solo se modifica uno de los archivos (prog1.cpp), entonces solo hace


falta recompilar ese.
1 $$ g++ -o prog1.o -c prog1.cpp
2 $$ g++ -o prog prog1.o prog2.o

Para mejor organizacion, si hay muchos *.o conviene ponerlos en una


librera
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 librera puede ser que haya sido desarrollada por un tercero:
libpetsc.a, libmkl.a.

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 14


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

El preprocesador CPP

Muchas veces hay texto que se repite muchas veces en el codigo. En ese
caso se pueden usar macros
1 int v[100000];
if (n<100000) {
....
2
3
4 }
Se puede simplificar de la siguiente forma
1 #define MAX 100000
2 int v[MAX];
if (n<MAX) {
....
3
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 Ingeniera y Ciencias Hdricas FICH - UNL slide 15


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

El preprocesador CPP (cont.)

CPP solo realiza manipulaciones a nivel de texto, no conoce nada


especfico del lenguaje C/C++, incluso puede usarse (y se usa) para otros
lenguajes como Fortran.
Las directivas mas 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, despues se puede llamar al macro en otros
lugares del codigo y es reemplazado por su expansion. Los macros
pueden tener argumentos. Por convencion se suele dar a los macros
nombres en mayusculas.
Se puede conocer cual es el resultado del CPP llamando a g++ con la
opcion -E
1 $$ g++ -o tempo.cpp -E prog.cpp
El CPP es un programa separado que se puede llamar por s mismo
Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 16
((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

(/usr/bin/cpp).

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 17


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Chequeo de tipos

C++ es un lenguaje tipado (aka tipeo estatico, en ingles 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 compilacion. Esto es bueno porque
permite detectar tempranamente errores. (Es equivalente al chequeo de
unidades en Fsica).
1 // error: asigna un string a una variable entera
2 int a;

3 a = "Hello";

Otros lenguajes (sobre todos los interpretados) hacen chequeo dinamico


de tipo, esto implica una perdida de eficiencia.
El chequeo se hace tambien para los argumentos de una funcion
1 void fun(int a,string s);
2 . . .

3 fun(23,45); // ERROR (45 no es un string!)

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 18


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Compilacion por separado

En C++ se favorece que un programa grande se pueda dividir en


fracciones mas pequenas. El mecanismo fundamental para dividir un
programa en partes mas pequenas es usar funciones que realizan tareas
bien definidas. Por ejemplo podemos pensar en una funcion int
gcd(int,int); que toma dos enteros y retorna el maximo comun divisor
de los mismos.
Las funciones tienen argumentos, una vez que la funcion termina su
tarea, retorna un valor. Tambien puede ser que las funciones tengan
efectos colaterales (side effects) es decir que modifiquen sus
argumentos u otros objetos.

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 19


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Compilacion por separado (cont.)

Para crear un programa que este dividido en varios archivos, el codigo de


un archivo debe poder usar las funciones del otro. Supongamos que un
archivo prog1.cpp contiene a la funcion gcd(). Si queremos usar a gcd()
en el codigo 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 funcion en prog2.cpp antes de
poder llamarla
int gcd(int,int); // declara gcd()
...
1
2

3 r = gcd(m,n); // la puede usar porque ya


4 // fue declarada

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 20


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Declaraciones y definiciones

Una declaracion le dice al compilador que esa funcion 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 definicion por otra parte dice especficamente como la funcion 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 21


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Declaraciones y definiciones (cont.)

Cada funcion puede estar declarada varias veces en un archivo (mientras


la signatura de la funcion sea la misma en cada una de las declaraciones).
int f(int x);
...
1
2

3 int f(int); // OK, misma signatura

Por el contrario, la funcion solo puede estar definida una sola vez en todos
los archivos del programa, ya que si no el compilador no sabra cual usar.
1 // archivo prog1.cpp
2 int f(int x) { return 2*x; }
3

4 // archivo prog2.cpp
5 int f(int) { return 3*x; }
6 // -> ERROR: multiplemente definida

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 22


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Definiciones y declaraciones de variables

Si declaramos una variable, por ejemplo


1 int m;
si bien parace una declaracion, en realidad ya tiene toda la informacion para
construir al objeto (un entero de 4 bytes) por lo tanto el compilador lo toma
ademas como una definicion. Por eso no podemos incluir dos veces esta
declaracion/definicion, aunque sea del mismo tipo.
int m;
...
1
2

3 int m; // ERROR

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 23


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Definiciones y declaraciones de variables (cont.)

Si queremos forzar a que sea una declaracion y no una definicion


entonces debemos usar el keyword extern
extern int m;
...
1
2

3 extern int m; // OK
4 . . .

5 int m; // OK

extern se puede usar tambien con las funciones, para hacer hincapie en
que es una declaracion, por ejemplo
1 extern int f(int x);
pero no es necesario.

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 24


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Incluyendo headers

Es usual que en nuestros programas escribamos una serie de funciones


que despues 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);
double sin(double alpha);
...
4
5
6 int x = gcd(m,n);
7 double c = cos(alpha);
double s = sin(theta);
...
8
9

Esto se vuelve muy engorroso si hay que incluir las declaraciones en cada

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 25


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 despues en prog1.cpp hay que solo incluir el header:
1 // prog1.cpp
#include "utils.h"
...
2
3

4 int x = gcd(m,n);
5 double c = cos(alpha);
double s = sin(theta);
...
6
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 Ingeniera y Ciencias Hdricas FICH - UNL slide 26


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 compilacion
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
#include <src/utils5.h>
...
4
5

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 27


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Usando libreras

Entonces si tengo que usar una librera matrix que esta 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 librera 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 librera basta con incluir el header
1 // myprog.cpp

2 #include <matrix.h>
3 . . .

y al linkeditar incluir la librera


1 $$ g++ myprog.cpp /usr/lib/libmatrix.a -o myprog

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 28


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Formato de include para C++

La extension que se usa para los archivos fuente puede ser .cpp, .cxx.
Para los headers se utiliza .h, .hpp, .hxx.
Para evitar confusiones y ambiguedad con las extensiones, C++ introdujo
el concepto de include sin extension. El traductor se encarga de convertir
el nombre y buscar la extension.
1 #include <matrix>
Existe una librera con muchas funciones muy utiles que es estandar de C
y se llama justamente libc.a. Entre otras incluye funciones
. Matematicas 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 29


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Un primer programa en C++

Para imprimir por terminal hay que usar el operador << de la clase
iostream:
#include <iostream>
...
1
2

3 cout << "Hola";


El operador << en C quiere decir en realidad otra cosa: es para desplazar
los bits en un numero 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 30


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Namespaces

A medida que una librera o programa crecen cada vez hay mas funciones
y es muy posible que se produzca la colision de nombres. Por ejemplo, si
escribo una librera para manipular matrices, puedo querer implementar
una funcion rand() que llena la matriz con numeros aleatorios.
Lamentablemente la libc ya usa el nombre rand() para generar un unico
numero aleatorio.
Una solucion que se usaba en C era prependizar un prefijo identificador
de la librera a todas las funciones de la misma matrix_rand(),
matrix_sum(), matrix_prod(). Esto se vuelve muy engorroso.

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 31


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Namespaces (cont.)

C++ provee un mecanismo para evitar colisiones llamado namespaces.


Todos los archivos de la librera 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 despues 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 librera 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 32


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Namespaces (cont.)

Muchas utilidades y variables estandar de C++, por ejemplo cout, estan en


el namespace std de manera que o bien hay que hacer
1 std::cout << "Hola";
o si no
using namespace std;
...
1
2

3 cout << "Hola";

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 33


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Estructura de un programa

Un programa en C/C++ esta compuesto de una coleccion de funciones y


variables. Cuando uno lanza el programa hay que determinar donde se
empieza a ejecutar el codigo, o sea el punto de entrada. En C/C++ el punto
de entrada es la funcion main().
La definicion de una funcion consiste en un valor de retorno, el nombre
de la funcion y su lista de argumentos. El cuerpo de la funcion (las
instrucciones que la componen) van entre llaves.
1 int function() {
2 // Function code here (this is a comment)
3 }

Puede haber mas pares de llaves balanceadas ({}) adentro de la funcion


pero debe haber uno mas externo que define el cuerpo de la funcion.
Como main() es una funcion, debe respetar estos requisitos. main() no
tiene argumentos y retorna un int.

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 34


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Estructura de un programa (cont.)

C/C++ es un lenguaje de formato libre (free form), la indentacion o la


posicion de las variables en la lnea son irrelevantes.
Tampoco es relevante la cantidad espacio en blanco (espacios, tabs, fin
de lnea). Cualquier cantidad de estos caracteres juntos es equivalente a
un solo espacio. De hecho un programa en C++ podra escribirse ne una
sola lnea.
En C los comentarios van encerrados entre /* y */ (comentario multilnea).
En C++ se agrego un nuevo tipo de comentario que es por lnea desde un
// hasta el final de la lnea. (Esto viola un poco el concepto de free form).
1 /* Comentario multilinea tipo C */
2 int /* comentario en el medio del codigo */ x;
3 // Comentario por linea tipo C++

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 35


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 lnea.
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
mas potente. A los strings de C se los debe llamar mas 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 lnea, \t un TAB, \0 un NULL, \\ una
barra invertida.
Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 36
((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Concatenacion de arreglos de caracters

Para incluir arreglos de caracteres muy largos se puede simplemente


poner uno a continuacion de otro (puede ser en diferentes lneas). El CPP
se encarga de juntarlos todos en una sola lnea: "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 effects\nas long as there is no "
9 "punctuation separating adjacent character "
10 "arrays.\n";
11 }

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 37


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 38


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Llamando a otros programas

Dentro de la librera estandar de C hay una funcion 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 ejecutara en la lnea 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 39


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 40
((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Strings de C++

Para eso C++ tiene objetos llamados strings que permiten manipularlos en
forma mucho mas simple y con menor probabilidad de error.
1 #include <iostream>
2 #include <cstring>
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 Ingeniera y Ciencias Hdricas FICH - UNL slide 41


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 42


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Escribir y leer de archivos

Las funciones estan 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 funcion getline(stream,s) lee una lnea 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 43


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Escribir y leer de archivos (cont.)

Otro ejemplo es guardar todo el archivo en un solo 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 lnea en un string separado?

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 44


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

La clase vector

Un vector es un contenedor que permite guardar un numero indefinido de


elementos en forma contigua e indexada.
Se puede agrandar o achicar en forma dinamica, sin perder los elementos
preexistentes.
Esta templatizado o sea que se pueden definir vectores de diferentes
tipos: vector<int>, vector<double>, vector<string>,...
La funcion push_back() permite agregar un nuevo objeto al final del vector.

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 45


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 46


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

La clase vector (cont.)

vector tambien 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 47


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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
especfica en un archivo. Ayuda: usar == para comparar strings.
4. Escribir un programa que imprime las lneas de un archivo de texto en
orden inverso.

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 48


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

El C en C++

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 49


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Funciones

Para evitar errores, C/C++ usa el concepto de prototipo o signatura de


funciones.
Antes de usar una funcion hay que declararla.
Al usar la funcion 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 algun lugar la funcion tiene que estar definida, aqu los nombres de los
argumentos tienen que aparecer para poder ser usados en la funcion
1 int translate(float x, float y, float z) {
2 x = y = z;
3 // . . .
4 }

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 50


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Valores de retorno

La declaracion de la funcion debe indicar el valor de retorno. Si la funcion


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 funcion retorna void entonces no se debe llamar a return.
Se puede tener mas de un return en la funcion. Son puntos de salida.
El valor de retorno debe ser compatible con el indicado en la declaracion.

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 51


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 52


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Usando la librera estandar de C

C incluye una librera de funciones estandar (tambien 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 estan 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 documentacion de las libreras usualmente incluye la declaracion de la
funcion y en que header (archivo .h) esta.
En caso que la librera no este documentada hay que directamente ver los
headers para encontrarel prototipo de la funcion.

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 53


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Control de ejecucion. True and False

Todas los condicionales (por ejemplo if o while) usan expresiones logicas


como por ejemplo el resultado del operador de comparacion A==B. Esta
expresion retorna directamente un valor logico true o false. No confundiir
con el operador de asignacion A=B.
Lo mismo ocurre con otros operadores de comparacion
1 A==B; //Its equal?
2 A!=B; //Its distinct?
3 A<B; //Its smaller?
4 A<=B; //Its smaller or equal?
5 A>B; //Its greater?
6 A>=B; //Its greater or equal?
Si la expresion no retorna un valor booleano, entonces C trata de convertirlo.
Para todos los valores numericos (enteros, float, double, char, punteros) el
valor es falso si es cero, y en cualquier otra caso es verdadero. Entonces por
ejemplo el valor logico de las siguientes expresiones es equivalente
1 if (n) { . . . }
2 if (n!=0) { . . . . }
Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 54
((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

3 if (!(n==0)) { . . . . } // ! is negation

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 55


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 56


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 << "Its greater than 5" << endl;
6 else
7 if(i < 5)
8 cout << "Its less than 5 " << endl;
9 else
10 cout << "Its 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 57


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

If-else (cont.)

Notar que todo el if actua como una sola instruccion, por eso no hace falta
encerrarlo con un {}.
1 if(i > 5)
2 cout << "Its greater than 5" << endl;
3 else
4 if(i < 5)
5 cout << "Its less than 5 " << endl;
6 else
7 cout << "Its equal to 5 " << endl;
8
9 // es equivalente a
10
11 if(i > 5) { cout << "Its greater than 5" << endl; }
12 else {
13 if(i < 5)
14 cout << "Its less than 5 " << endl;
15 else
16 cout << "Its equal to 5 " << endl;
17 }
Es una convencion mut util indentar ambos bloques del if para mejorar la

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 58


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

legibilidad.

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 59


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

while

while, do-while y for controlan lazos (loops) de ejecucion.


1 while(expression)
2 statement
Como antes statement puede ser simple o compuesto. La expresion se evalua
hasta que la condicion de falso. Para que el lazo termine en algun momento
es necesario que statement tenga algun efecto que haga que eventualmente
expression de falso
1 int x=0;
2 while (x<5) x=2; // ejecuta una vez el lazo
3 while (x<5) x=34; // ejecuta indefinidamente
4
5 x=0;
6 while (x<5) x++; // ejecuta el bloque 5 veces

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 60


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

while (cont.)

1 // Guess a number (demonstrates while)


2 #include <iostream>1
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 Ingeniera y Ciencias Hdricas FICH - UNL slide 61


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

while (cont.)

En C la condicion dentro del condicional puede ser tan elaborada como se


quiera, la unica restriccion es que debe retornar un valor logico (o convertible
a logico), incluso puede ser que el cuerpo del lazo este vaco
1 while(/* Do a lot here */) ;
2

3 while() { }
por ejemplo
1 while(is-prime(n)) n++; // busca el primer n no primo

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 62


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

do-while

1 do
2 statement
3 while(expression);
Es similar al while pero ahora statement es ejecutado antes de verificar la
condicion.
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 Ingeniera y Ciencias Hdricas FICH - UNL slide 63


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 64


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Lazo for (cont.)

continue es similar a break pero hace que se ejecute la siguiente iteracion 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 65


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 numero compuesto" << endl;
6 }
Si hay mas de un lazo anidado entonces break sale del lazo mas 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 }

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 66


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 << "Its an a" << endl; break;
5 case b: cout << "Its a b" << endl; break;
6 default: cout << "Neither a or b" << endl;
7 }

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 67


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Si no se incluyen los break entonces la ejecucion sigue al siguiente case.

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 68


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

goto

La sentencia goto permite saltar a otro punto del programa. Se lo considera


muchas veces como una mala practica de programacion, aunque a veces
puede ser util, por ejemplo para saltar de varios lazos anidados cuando se
encuentra una condicion.
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 Ingeniera y Ciencias Hdricas FICH - UNL slide 69
((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

17 }

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 70


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Recursion
Muchos problemas son intrnsecamente recursivos, es decir la solucion de un
problema esta dada por la solucion de uno menor con el mismo algoritmo,
por ejemplo la definicion de factorial se puede hacer en forma recursiva

n! = n (n 1)! (1)

en realidad esto es cierto si n > 1, la definicion correcta es



1; si n = 1;
n! = (2)
n (n 1)! ; si n > 1

decimos que el caso n = 1 corta la recursion.


Usando llamadas recursivas a funciones podemos implementar la funcion
factorial
1 int factorial(int n) {
2 if (n==1) return 1;
3 else return n*factorial(n-1);
4 }

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 71


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Recursion (cont.)

La recursion es muy elegante para resolver problemas, pero puede ser


demandante en terminos de recursos. Es mas 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 asociativos como +, operadores
logicos, concatenacion de strings...

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 72


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Operadores

Los operadores no son mas que funciones, con una sintaxis especial. Un
operador toma una o mas 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 cuestion importante con los operadores es la precedencia de los
mismos. Para los operadores matematicos 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
parentesis para forzar el orden en que se evaluan las expresiones.

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 73


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Operadores de auto incremento

El operador ++ es un atajo para una operacion muy comun en programacion:


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 funcion 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 74


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Operadores de auto incremento (cont.)

Tambien 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 75


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Tipos de datos

Dijimos que C/C++ es un lenguaje de tipeo estatico, 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 estan definidos en el compilador,
y tambien el programador puede crear sus propios tipos, muchas veces por
composicion. 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 numero 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 numero de punto flotante con al menos 4 bytes (simple precision)
double un numero de punto flotante con al menos 8 bytes (doble
precision).

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 76


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 77


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Tipos de datos (cont.)

Como los tipos basicos tienen una cantidad de bits fija pueden representar un
tamano maximo. Por ejemplo los enteros de 16 bits solo pueden estar entre
-32768 y +32768. Ademas el tamano del tipo (la cantidad de bits) puede
depender de la maquina y del compilador, entonce los valores maximos y
mnimos (los lmites) estan 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 78


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Especificadores

Para representar enteros se utiliza un bit de los 32 disponibles para


representar el signo.
Si solo 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 79


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 80
((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 81


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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: reserveme 4 bytes de la memoria y a partir de ahora lo voy a llamar n. El
operador & nos muestra en que posicion 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
quisieramos 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 82


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 83


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 84


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Punteros (cont.)

La direccion 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 solo una
convencion).

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 85


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 direccion de una
variable, lo cual nos permite modificarla a traves de ese proxy
1 int number=100;
2 int *number-p = &number;
3 *number-p = 25; // Ahora number contiene 25!!

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 86


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Punteros (cont.)

OJO: el hecho de declarar una variable de tipo puntero no significa que


este apuntando a un objeto valido, es deber del programador asignarle al
puntero una posicion valida, si no puede dar error en tiempo de ejecucion
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 Ingeniera y Ciencias Hdricas FICH - UNL slide 87


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Punteros (cont.)

Los punteros tienen un monton de usos, el primero que podemos ver aca
es el de causar que una funcion modifique un objeto
1 #include <iostream>
2 using namespace std;
3

4 void f(int a) {
5 cout << "a = " << a << endl;
6 a = 5;
7 cout << "a = " << a << endl;
8 }
9

10 int main() {
11 int x = 47;
12 cout << "x = " << x << endl;
13 f(x);
14 cout << "x = " << x << endl;
15 }

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 88


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Punteros (cont.)

Imprime:
1 x = 47
2 a = 47
3 a = 5
4 x = 47
Como la variable a en f() es una copia, resulta que la modificacion que se
hace en f() no persiste, de manera que queda el mismo valor.

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 89


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Punteros (cont.)

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 Ingeniera y Ciencias Hdricas FICH - UNL slide 90


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Punteros (cont.)

Imprime:
1 x = 47
2 &x = 0065FE00
3 p = 0065FE00
4 *p = 47
5 p = 0065FE00
6 x=5

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 91


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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
dereferenciacion.
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;
Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 92
((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

18 }

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 93


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Referencias (cont.)

Imprime:
1 x = 47
2 &x = 0065FE00
3 r = 47
4 &r = 0065FE00
5 r=5
6 x=5

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 94


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Punteros a void

El compilador solo acepta que asignemos a una variable de tipo int* la


direccion 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 95


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Punteros a void (cont.)

Una vez que una direccion 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 ejecucion
1 int i = 99;
2 void* vp = &i;
3 // Compila OK, posible error en tiempo de ejecucion
4 *((string*)vp) = "Hello world";

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 96


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Scope de las variables

Una variable existe desde su definicion 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 97
((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 98


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 99
((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

19 while(char c = cin.get() != q) {
20 cout << c << " wasnt 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 100


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Definiendo variables on-the-fly (cont.)

Las variables que estan fuera de todas las funciones son globales, su scope
es todo el programa, includo 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 101
((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

19 globe = 47;
20 }

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 102


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Variables locales
Las variables que existen dentro de un scope son locales, tambien se les
llama automaticas 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 103
((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 104


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 105


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

19 a en h() despues de asignar: 234


20 [mstorti@galileo garage]$$

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 106


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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;
p = &z;
...
4
5
6 }
7 // ERROR (z no existe mas)
8 cout << "contenido de *p " << *p << endl;

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 107


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Variables estaticas

Si queremos que el area asignada a una variable local sea siempre el mismo,
entonces le agregamos el keyword static. Un ejemplo clasico es una funcion
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 Ingeniera y Ciencias Hdricas FICH - UNL slide 108


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Variables estaticas (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 Ingeniera y Ciencias Hdricas FICH - UNL slide 109


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Constantes

Si se utilizara muchas veces un valor que es constante se pueden hacer a


traves de un macro
1 #define PI 3.141459
o bien a traves de una variable de tipo const
1 const double pi = 3.141459;
Es mas prolijo esto ultimo (le permite al compilador hacer chequeo de tipo).

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 110


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Operadores. Asignacion

El caracter = se utiliza como el operador de asignacion:


1 A=4;
Lo que esta a la izquierda de = es el lvalue y lo que esta a la derecha el rvalue.
El rvalue puede ser cualquier expresion. El compilador la evalua y asigna el
resultado a lo que esta en el lvalue. Ahora bien lo que esta 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 111


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Operadores matematicos

Los operadores matematicos binarios usuales son +-*/. Cada uno de ellos se
puede usar en forma de acumulacion +=, -=, *=, /=. Por ejemplo
1 x += 5;
es equivalente a
1 x = x + 5;

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 112


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Operadores relacionales

Son
1 >, <, >=, <=, ==, !=

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 113


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Operadores logicos

Son && (and) y || (or). Recordar que en C/C++ muchos tipos se castean
automaticamente a bool, siendo 0 el valor falso y cualquier otro valor
verdadero. Cuando se imprimen los valores booleanos dan 0 o 1. ! es la
negacion.
Son operadores cortocircuitados es decir si hacemos
1 expr1 && expr2
entonces primero se evalua expr1 y si da falso, entonces expr2 NO se evalua,
ya que no es necesario porque la expresion logica resultara en falso de todas
formas. Eso puede ser importante, por ejemplo
1 if (n>0 && m/n!=3) . . .
esta garantizado que no dara error si n==0 ya que si es as directamente la
division por n no se hara. Lo mismo ocurre en
1 expr1 | | expr2
si la primera da verdadero.

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 114


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

El operador hook

Es una forma muy compacta de escribir un if-else. Por ejemplo esta expresion
calcula el mnimo de dos valores
1 x = (m<n ? m : n);
Se puede usar tambien en un lvalue. La siguiente expresion asigna al menor
de m,n el valor 23.
1 (m<n ? m : n) = 23;

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 115


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 parentesis.
No confundir = con ==.

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 116


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Operadores de cast

Si el compilador ve que estamos mezclando tipos en una asignacion,


insertara una operacion de cast (conversion de tipo) automaticamente
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 Ingeniera y Ciencias Hdricas FICH - UNL slide 117


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Operador sizeof

Retorna el tamano 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 118


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 basicos, mas complicado para punteros


1 typedef int *int p;
-
La regla es que se escribe una lnea como la declaracion de una variable
con typedef al principio y reemplazando la variable por el tipo.
Esto permite hacer expresiones mas cortas pero ademas 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 precision:
1 typedef double scalar;

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 119


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 a;
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 Ingeniera y Ciencias Hdricas FICH - UNL slide 120


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 121


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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;
c1
next
c='a' x=1

c3 c2
next next
c='c' x=3 c='b' x=2

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 122


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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
cp 0x7fff571b2d20, c a, x 1
...
5
6

7 cp 0x7fff571b2d20, c a, x 1
8 cp 0x7fff571b2d00, c b, x 2
9 [mstorti@galileo garage]$$

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 123


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Arrow operator

Como en el ejemplo anterior es muy comun la compinacion (*cp).x es decir


tener un puntero a una estructura cp y querer tomar un miembro x de la
estructura apuntada. Como es tan comun hay un atajo sintactico 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 124


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Enums

Supongamos que queremos definir una estructura shape que contiene una
forma geometrica, 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 crculos, 1=cuadrados, 2=rectangulos.
1 struct shape {
2 double x,y;
3 int gtype;
4 };
Entonces una funcion que imprime la forma sera 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
else if (s.gtype==2) //. . . imprime un rect
...
4
5
6 }
El problema con esto es que tenemos que guardar mentalmente una tabla
para saber que entero corresponda a cada forma.

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 125


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Enums (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
else if (s.gtype==RECTANGLE) //. . . imprime un rect
...
8
9
10 }

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 126


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Enums (cont.)

Pero, como ya dijimos, es preferible no usar macros, para esto esta 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
else if (s.gtype==rectangle) //. . . imprime un rect
...
11
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 especfico
1 enum GeoType { circle=5, square=10, rectangle=15};

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 127


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Arreglos de estructuras

Vimos que podemos definir arreglos como int v[100].


Tambien lo podemos hacer con estructuras cell sv[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 << "] "


<< (long int)&cellv[j] << endl;
9 . . .
8

10 &cellv[0] 140736201505632

11 &cellv[1] 140736201505648

12 &cellv[2] 140736201505664

ya que el tamano de la celda es de 16 bytes (8 para el doble y 8 para el


puntero):
cout << "sizeof(cell): " << sizeof(cell) << endl;
...
1
2

3 sizeof(cell): 16
Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 128
((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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];
cout << v << endl;
...
2
3

4 -> 0x7fff7e388420
Esto es porque el compilador solo almacena para el vector la direccion donde
comienza el area asignada al vector. Esto lo podemos verificar imprimiento la
direccion del primer elemento
1 cout << &cellv[0] << endl;
2 -> 0x7fff7e388420

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 129


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Punteros y arreglos (cont.)

Si tomamos un puntero al primer elemento podemos manipular al vector a


traves de ese puntero
1 int v[100];
2 int *p= &v[0];
3 for (int j=0; j<1000, j++) *(p+j) = 100*j;
De hecho en la mayora 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 130


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Arreglos de punteros

Tambien 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 131


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 lnea de
comando por whitespace y construye un arreglo de strings
Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 132
((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Arreglos de punteros (cont.)

El acceso a elementos de un arreglo de C es extremadamente rapido.


Sin embargo si se accede a posiciones mas alla de la ultima posicion del
vector se puede producir un error
int v[100];
2 . . .
1

3 v[100] = x; // Muy probablemente SIGSEGV o SEGFAULT

Se debe conocer el tamano del vector en tiempo de compilacion (hay una


forma de hacerlo dinamico, con new[]/delete[] o malloc()/free().
La clase vector<> es mucho mas versatil y mas segura.

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 133


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Arreglos de punteros (cont.)

Podemos verificar que los elementos de un vector estan 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 134


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Aritmetica 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 135


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Aritmetica 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 136


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Tamanos de estructuras

Cuando se usan estructuras con tipos mezclados puede ser que el tamano del
tipo combinado no sea igual a la suma de los tamanos 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 137


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Programacion Orientada
a Objetos

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 138


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Abstraccion 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 139


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Abstraccion 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 };
size

used free
store

quantity
next

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 140


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Abstraccion 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 141
((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 142
((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 143


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Abstraccion de datos (cont.)

CStash es un tipo que permite almacenar una cantidad ilimitada de


elementos de tamano size.
Tiene un area de almacenamiento interno unsigned char *storage.
Se pueden agregar elementos con add(), si el tamano 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 tamano de los elementos al valor entrado por el
usuario (int sz).
add() agrega un elemento copiandolo byte por byte a storage. Si el tamano
no es suficiente llama a inflate() para alocar una nueva area recopiando
todo el area previa y agregando el nuevo elemento.
quantity es el numero de lugares disponibles
next es la cantidad de lugares realmente ocupados.
fetch() retorna el puntero al lugar donde comienza el elemento en la
posicion index. Primero chequea que efectivamente el ndice este en el
rango de valores apropiados (0<=index<next). En caso contrario retorna un
puntero nulo. Esta garantizado que el puntero nulo no apunta a ningun
Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 144
((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

lado de la memoria.
count() retorna la cantidad de elementos que hay en el contenedor.
Simplemente retorna next.
Alocacion dinamica de memoria: Como no sabemos en principio que
tamano va a tomar el area de memoria vamos alocando dinamicamente
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 alocacion 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 alocacion da un error (OJO que no necesariamente retorna un
puntero nulo).
Los pedazos de memoria alocados con new pueden crear fragmentacion
de la memoria. (No hay un defragmentador).

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 145


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Abstraccion 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 146


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 147


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Abstraccion 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
fetch(&intStash, 3) = 3
...
5
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>
3: #include <string>
...
13
14
15 37: cleanup(&stringStash);
16 38: return 0;
17 39: }
18 freeing storage
19 freeing storage
20 [mstorti@galileo garage]$
Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 148
((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

POO basica

La librera que creamos tiene dos problemas basicos:

Sera bueno que la construccion y destruccion de los objetos fuera


automatica.
Polucion del espacio de nombres: Si necesitamos otro contenedor no
vamos a poder usar los nombres initialize() y cleanup(). Una posible
solucion sera usar nombres con prefijos CStash_initialize(),
CStash_cleanup() ...

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 149


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

POO basica (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 Ingeniera y Ciencias Hdricas FICH - UNL slide 150


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

POO basica (cont.)

Ahora las funciones aparecen dentro de la estructura, de manera que esta


actua 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
automaticamente llamando a la funcion como miembro de un objeto
1 Stash s1,s2,s3;
2 s1.initialize(10);

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 151


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

POO basica (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 Ingeniera y Ciencias Hdricas FICH - UNL slide 152
((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 153
((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 154


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

POO basica (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 solo 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) {
cout << "this: " << this << endl;
...
2
3
4 }
5

6 Stash s1;
7 cout << "&s1: " << &s1 << endl;
8 s1.initialize();
Imprimen el mismo puntero.

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 155


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

POO basica (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 Ingeniera y Ciencias Hdricas FICH - UNL slide 156
((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 157


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

POO basica (cont.)

Las llamadas a funciones de la librera se convierten as


1 CStash initialize(&s1,sz);
-
2 s1.initialize(size);

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 158


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Inclusion de headers

Algunos headers pueden incluir a otros, por ejemplo el header de una


librera lib1.h puede incluir iostream. Entonces si otra librera lib2.h
tambien incluye iostream, al querer incluir a las dos libreras
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 inclusion.
Podemos usar los macros para incluir condicionalmente partes del
codigo.
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 solo uno de los bloques se
compila. Quiere decir que se puede usar para usar diferentes pedazos de
Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 159
((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

codigo que de otra forma no compilara. 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 tambien


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
-
3 . . .
2

4 #undef MAX SIZE


-
5 #define MAX SIZE 1000 // OK!
-

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 160


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Inclusion de headers (cont.)

Para evitar la doble inclusion se utiliza un macro de proteccion


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 Ingeniera y Ciencias Hdricas FICH - UNL slide 161


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 explcitamente (e.g. std::cout).
Lamentablemente esto producira que si un usuario incluye mylib.h todo
su codigo pierde la proteccion del namespace y volvemos a la situacion
que queramos impedir con los namespace: la colision de nombres.
Por lo tanto la regla es: NO usar using namespace.. en los headers, solo en
los .cpp

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 162


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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
data next data next data next data next
head

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 163


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 164


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Estructuras enlazadas (cont.)


La funcion 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
inicializacion y destruccion de la estructura.
El tipo de las celdas Link solo se usara con la clase Stack. Si nuestra
librera quiere ademas definir un tipo Queue que representa una cola, con
celdas enlazadas, entonces no podra usar el mismo nombre Link para sus
celdas.
Para evitar esta colision 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 165
((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

11 void cleanup();
12 };

Notar que al definir el tipo Link en la misma declaracion del tipo se define
un puntero Link *head a la primera celda. Por supuesto se puede hacer
por separado tambien
struct Link {
...
1
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 funcion de inicializacion
initialize().
Link no tiene cleanup(), el mismo usario es responsable de liberar el
espacio apuntado por data, si existe.

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 166


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 167
((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 168


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 169
((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

21 while((s = (string*)textlines.pop()) != 0) {
22 cout << *s << endl;
23 delete s;
24 }
25 textlines.cleanup();
26 }

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 170


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Mas 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 171


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 funcion 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 codigo y prevenir la colision de nombres, la OOP
(Programacion Orientada a Objetos) es mucho mas que esto.

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 172


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Ocultando la implementacion

Una librera tpica de C consiste de una o mas definiciones de estructuras


(struct) y funciones asociadas que actuan sobre dichas estructuras. En C++
las funciones se pueden asociar explcitamente a esas estructuras poniendo
sus declaraciones dentro del scope de la estructura.
Pero hay una cuestion adicional que es hasta donde el programador debe
permitir que el usuario de la librera manipule a la estructura. Si el usuario lee
las definiciones de la estructura puede por s mismo manipular la estructura.
Ahora bien, si en algun momento el programador cambia la forma en que esta
armada la estructura el codigo del usuario dejara de funcionar (breaks the
code).
Por ejemplo en la estructura Stack definida previamente el programador
podra en el futuro decidir que es mejor alocar la memoria de a grandes
chunks de 100 elementos o mas que alocar de a uno como esta hecho en esa
implementacion. Si el codigo del usuario depende de que la alocacion se
haga de a un elemento, entonces al producirse el cambio de implementacion
su codigo dejara de funcionar.

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 173


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Ocultando la implementacion (cont.)

En C esto se puede resolver parcialmente si el programador especifica en la


documentacion de la librera las funciones con las cuales el usuario de la
estructura debe manipular los objetos a traves de las funciones provistas, y
hasta que punto puede usar directamente los datos almacenados en la
estructura. Pero esto es solo 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 174


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Control de acceso a los miembros


El acceso a los miembros de una estructura en C++ se hace a traves 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 175


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Control de acceso a los miembros (cont.)

La clave keyword private por el contrario, indica que los miembros


correspondientes solo se pueden acceder desde codigo (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 Ingeniera y Ciencias Hdricas FICH - UNL slide 176
((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

19 b.func(); // OK, public


20 b.j = 1; // Illegal, private
21 b.f = 1.0; // Illegal, private
22 }

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 177


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 sera explicado mas adelante
cuando se explique el concepto de herencia.

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 178


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Amistad (Friendship)

El keyword friend permite declarar que una funcion 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 179
((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 180
((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 181


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Anidamiento (nesting) y amistad

El estandar 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 practica el GCC da acceso a la clase externa a la clase
interna, pero no al reves. Es decir da error en 1 y 2, pero no en 3.

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 182


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Object layout

Una de las condiciones de diseno de C++ fue que codigo valido en C debera
compilar sin problemas en C++. Por esto las construcciones de tipo struct
tienen a todos sus miembros publicos.
Cuando el compilador organiza los datos dentro del objeto los guarda en
memoria en forma contigua, en el orden en el que estan 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
publicos de la clase) tiene sentido solo en el momento de compilacion. Una
vez que el codigo fuente es convertido a codigo de maquina dos estructuras
que difieren solo en cuanto a sus secciones private y public son
indistinguibles entre s, a menos del efecto discutido previamente de la
disposicion en la memoria (object layout).

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 183


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Clases
Controlar el acceso a los miembros de una estructura es parte de lo que se
llama ocultar la implementacion (implementation hiding). Esto es un
concepto clave en OOP.
En OOP se trata de ocultar lo mas posible los miembros de la estructura, por
eso lo deseable sera 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 184
((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 185


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Clases (cont.)

Vemos la clase Stash ahora con control de acceso. Todos los datos son
privados. La funcion inflate() tambien ya que solo 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 186


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Clases (cont.)

En Stack ahora hacemos que toda la estructura Link sea privada o sea solo 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.
Podramos tambien declararla como clase, pero entonces deberamos
declarar friend a Stack.
Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 187
((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Ocultando totalmente la implementacion

Todava uno podra preguntarse si se puede ocultar aun mas la


implementacion. Que el usuario vea solo la parte publica. Otra razon es evitar
la recompilacion innecesaria. Una solucion es usar punteros opacos, (aka
handles, en C++ se usa tambien el nombre Cheshires cat). Por ejemplo
podramos ocultar completamente los detalles de Stash como esta abajo. El
usuario solo 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 188
((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 189


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Inicializacion y cleanup

Uno de los errores mas comunes cuando se utilizan libreras es no inicializar


y destruir (cleanup) apropiadamente los objetos. En las libreras que hemos
descripto hasta ahora esto se haca con funciones initialize() y cleanup().
Una de las ideas que C++ toma de la OOP es que estas operaciones de
inicializacion y cleanup se hagan en forma automatica.
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 Ingeniera y Ciencias Hdricas FICH - UNL slide 190


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Inicializacion y cleanup (cont.)

Para esto debe haber dos funciones (una de inicializacion y otra de cleanup)
que tengan nombres especiales ya que deben ser llamadas automaticamente
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 Ingeniera y Ciencias Hdricas FICH - UNL slide 191


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 ningun 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 podra construir ningun objeto de la clase.
Si no declaramos ningun 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 192


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

El destructor

Asi como el constructor garantiza que se llama a la rutina de


inicializacion, el destructor (abreviado dtor) se encarga de realizar las
tareas de cleanup.
Es llamado automaticamente 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 193


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 194


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 195


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Eliminacion del bloque de definicion

Es tpico de C tener que definir todas las variables al principio de un scope


(por ejemplo de una funcion). Por el contrario C++ promueve que las variables
se definan lo mas cerca posible del punto en el que van a ser usadas. Esto se
pega con el uso automatico de constructores, ya que puede ser que el
compilador no tenga toda la informacion 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 196
((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 197


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 198


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 199
((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 200
((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 201


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 202


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 203
((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 204


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Initializacion 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 demas a partir del
constructor por defecto
1 int b[6] = {17};
Conteo automatico: automaticamente dimensiona c como c[4] a partir del
numero de elementos entre llaves.
1 int c[ ] = { 1, 2, 3, 4 };

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 205


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Inicializacion 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 206


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Sobrecarga de funciones

Vimos que el compilador decora los nombres de las funciones que


pertenecen a una clase (metodos) con el nombre de la clase
1 void f();
2 class X { void f(); };
Aca los nombres de las f no colisionan ya que son en realildad ::f() y X::f().
El compilador tambien 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 dara un error.) Esto se llama sobrecargar el
nombre de la funcion (en este caso print()). Sobrecargar quiere decir
entonces usar un mismo nombre para varias cosas diferentes.
Atencion: 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 207


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Sobrecarga de funciones (cont.)

Si compilamos y corremos la utilidad nm al archivo objeto nos da el nombre


interno de la funcion
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 Ingeniera y Ciencias Hdricas FICH - UNL slide 208


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Sobrecarga de funciones (cont.)

El nombre mangleado es difcil de identificar con respecto a la funcion


original. La opcion nm -C permite obtener un nombre mas legible. Esto es muy
util cuando queremos buscar si una librera tiene una dada funcion 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 librera 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 209


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 tamano del stash a partir del segundo
argumento. En cambio recordemos que Stash(int) dejaba al stash vaco.
Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 210
((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Argumentos por default

Otra posibilidad es que los dos ctores previos sean el mismo con un
argumento por default para el tamano
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 Ingeniera y Ciencias Hdricas FICH - UNL slide 211


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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
extern const int bufsize; // en un header
...
1
2

3 const int bufsize = 100; // en el .cpp

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 212


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 dara 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 213
((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Constantes (cont.)

Tambien 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 214


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 215


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 tambien para evitar la copia. Incluyendo el const permite pasar los
argumentos en forma eficiente, pero evitando que accidentalmente se
modifique el objeto.

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 216


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Const en clases

Si se quiere tener parametros de una clase, que son constantes, entonces no


solo hay que ponerle const, sino tambien static que quiere decir que ese
miembro es el mismo para todos los objetos de la clase. De esa forma actua
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 Ingeniera y Ciencias Hdricas FICH - UNL slide 217


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 metodos 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 218


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Objetos const y funciones de la clase (cont.)

Entonces el compilador chequea que si un objeto es const solo pueden ser


llamados sobre el funciones y metodos 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 219


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Chapter 5

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 220


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Funciones inline

Cada vez que hay una llamada a funcion hay un costo adicional de pasar
los argumentos por el stack a la funcion y hacer un jump de assemble.
Para evitar esto podemos usar el keyword inline que indica al compilador
que queremos que el codigo de esa funcion sea replicado en cada punto
en que lo llamamos.
La ventaja, como dijimos, es la eficiencia, se evita el mecanismo de
llamado a funcion en assemble.
La desventaja es que el codigo binario de la funcion aparece duplicado en
cada punto, con lo cual el ejecutable se hace mas grande. Tambien
implica que el codigo de la funcion 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 despues hacer la funcion realmente inline o no. A veces puede
hacerla no inline porque es muy compleja (e.g. tiene lazos) o porque en
algun punto se toma la direccion de la funcion.
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 Ingeniera y Ciencias Hdricas FICH - UNL slide 221


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 222


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Funciones inline (cont.)

Otra forma que habra para evitar el llamado a funciones sera no definir la
funcion sino que en cada punto que se usa incluir explcitamente su codigo.
Para evitar esto una forma que exista 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 codigo final se reemplaze la
llamada a MAX por la expansion del macro.

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 223


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 definicion apropiada se obtiene protegiendo los argumentos con
parentesis.
1 #define SQUARE(x) (x)*(x)

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 224


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Especificaciones de linkedicion

Cuando declaramos una funcion, digamos


1 void f(int x, char c);
dijimos que internamente el compilador la decora (tambien se llama a esto
mangling) a, por ejemplo, _Z1fcd. Esto es a efectos de poder despues
sobrecargar la funcion. Ahora bien, si queremos usar una librera 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 funcion
1 extern "C" void f(int x, char c);
Esto le dice al compilador que no decore el nombre de esa funcion. Notar que
por lo tanto esa funcion no puede ser sobrecargada.

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 225


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Especificaciones de linkedicion (cont.)

Como las declaraciones de las libreras estaran en headers de esas libreras,


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 libreras 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 226


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Referencias en C++
Vimos el concepto de referencia, basicamente 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 227


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Referencias en C++ (cont.)

Otro uso es para crear aliases locales para modificar una parte de un
contenedor mas grande, por ejemplo un arreglo de varias dimensiones
(tambien puede ser con los contenedores de las STL)
1 class A {
2 // . . . .
3 void f(); // modifica a *this
4 };
5

6 // arreglo multidimensional de As
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 Ingeniera y Ciencias Hdricas FICH - UNL slide 228


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 podramos crear una copia local y despues pisar el valor
en av
1 // arreglo multidimensional de As
2 int v[100][100][100];
3 // Un elemento particular de av
4 int x = av[i][j][k];
5 // . . . hace calculos con x
6 // Pisa el valor en av
7 av[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 Ingeniera y Ciencias Hdricas FICH - UNL slide 229


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Referencias en C++ (cont.)

De nuevo, una posibilidad es usar macros


1 // arreglo multidimensional de As
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.
Ademas cada vez que llamamos a AIJK estamos haciendo una cuenta con
i,j,k para encontrar la posicion correspondiente en v.

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 230


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Referencias en C++ (cont.)

Una posibilidad es usar punteros


1 // arreglo multidimensional de As
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 Ingeniera y Ciencias Hdricas FICH - UNL slide 231


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Referencias en C++ (cont.)

Esto es eficiente, y compacto pero hay que andar dereferenciando ap. Todava
mejor es usar referencias
1 // arreglo multidimensional de As
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 mas de la clase.

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 232


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 233


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 traves de a
6 }
7 }
8 }
No se puede hacer una referencia a NULL.
Hacer referencias es muy eficiente, igual que con punteros.

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 234


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 ademas 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 funcion no va a modificar los argumentos es todava mejor declarar a las
referencias como const
1 void f(const A &a,const B &b) {. . .}

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 235


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 contraposicion con una deep copy) y
puede traer problemas, sobre todo si el objeto contiene punteros a areas
de almacenamiento dinamico 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 236


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Sobrecarga de operadores

Sobrecarga de operadores es simplemente un aditivo sintactico (sintactic


sugar) para hacer llamadas a funciones de la clase en forma mas
compacta.
Los nombres de los operadores son operator@ donde @ puede ser algunos
de los operadores usuales, matematicos (+, -, *, /), de indexacion [], (),
incremento ++, --, acumulacion (+=, -=, *=, /=), logicos ||, &&, etc...
Hay operadores unarios y binarios. A veces el mismo operador puede ser
unario o binario dependiendo del contexto (por ejemplo *
(dereferenciacion como unario, producto como binario), +, -).
Cual de los operadores es llamado y sobre que objetos es a veces un
poco difcil de discernir.
Pueden ser metodos de la clase o pueden ser funciones globales
(declaradas friend)

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 237


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 238


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 239
((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 240


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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
exponenciacion, como en Fortran).
No se puede cambiar la regla de precedencia de los operadores.

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 241


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 242
((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 << "+Integer\n";
39 return a; // Unary + has no effect
40 }
41 const Integer operator-(const Integer& a) {
42 cout << "-Integer\n";
43 return Integer(-a.i);
44 }
45 const Integer operator(const Integer& a) {
Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 243
((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

46 cout << "Integer\n";


47 return Integer(a.i);
48 }
49 Integer* operator&(Integer& a) {
50 cout << "&Integer\n";
51 return a.This(); // &a is recursive!
52 }
53 int operator!(const Integer& a) {
54 cout << "bang Integer\n";
55 return !a.i;
56 }
57 // Prefix; return incremented value
58 const Integer& operator++(Integer& a) {
59 cout << "++Integer\n";
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 Ingeniera y Ciencias Hdricas FICH - UNL slide 244
((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

69 }
70 // Prefix; return decremented value
71 const Integer& operator--(Integer& a) {
72 cout << "--Integer\n";
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 Ingeniera y Ciencias Hdricas FICH - UNL slide 245
((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 << "+Byte\n";
105 return *this;
106 }
107 const Byte operator-() const {
108 cout << "-Byte\n";
109 return Byte(-b);
110 }
111 const Byte operator() const {
112 cout << "Byte\n";
113 return Byte(b);
114 }
115 Byte operator!() const {
116 cout << "bang Byte\n";
117 return Byte(!b);
Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 246
((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

118 }
119 Byte* operator&() {
120 cout << "&Byte\n";
121 return this;
122 }
123 // Side effects: non-const member function:
124 const Byte& operator++() { // Prefix
125 cout << "++Byte\n";
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 << "--Byte\n";
137 --b;
138 return *this;
139 }
140 const Byte operator--(int) { // Postfix
141 cout << "Byte--\n";
Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 247
((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 248
((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 249


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 250
((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 251
((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 252
((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 253
((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 254
((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 255
((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 256
((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 257
((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 258
((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 259
((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 260
((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 261
((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 262
((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 263
((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 264
((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 265
((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 266
((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 267
((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 268
((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 269
((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 270


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Sobrecarga de operadores binarios (cont.)

En los operadores de acumulacion (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


podran ser el mismo objeto, por ejemplo si hacemos
1 Integer A;
2 A += A;
Lo mismo pasa con el operador de asignacion operator=(). A esto se le
llama chequear por autoasignacion. Sobre todo si hay componentes
apuntadas por punteros.

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 271


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Chapter

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 272


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 actua como una funcion
(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 Ingeniera y Ciencias Hdricas FICH - UNL slide 273


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Creacion dinamica 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 estaticos son alocados en el momento de arrancar el


programa y viven durante toda la duracion del mismo.
Objetos dinamicos son alocados al entrar en el scope correspondiente.
La alocacion se hace en el stack.
Objetos pueden ser alocados y desalocados en cualquier momento
(responsabilidad del programador) en el heap.

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 274


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Uso de la memoria dinamica en C

En C la alocacion en el heap se hace con las funciones malloc() y free(). El


uso basico para objetos en C sera 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 275


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Uso de la memoria dinamica en C++

En C++ se trata que todas estas acciones sean hechas en lo posible en forma
automatica por el operador. Para esto las funciones malloc() y free() (que
despues de todo son funciones de librera es decir que no son parte del
lenguaje) son reemplazadas por operadores intrnsecos 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 276


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Uso de la memoria dinamica en C++ (cont.)

Como new se encarga de la inicializacion, tambien se puede llamar con


cualquier otro constructor, ademas del ctor por defecto
1 A *p = new A(x,y,z);
Tambien 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 explcitamente 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 277


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Porque 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 debera dar error de compilacion aunque dependiendo del
compilador puede que no lo de (sera una extension del compilador). De
todas formas siempre es mas restrictivo que alocar con new porque el arreglo
es desalocado y destruido cuando termina su scope.

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 278


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Memory exhaust

Que ocurre si se acaba la memoria? En viejos compiladores new retornaba un


puntero nulo. En el estandar actual lanza una excepcion de tipo bad_alloc().
Por compatibilidad con la version 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 279


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Composicion

Hasta ahora vimos clases/estructuras que se construyen a partir de tipos


basicos usando composicion.
1 class A {
2 private:
3 int i;
4 double x;
5 public:
6 char c;
7 void f();
8 };

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 280


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Composicion (cont.)

La idea es que las clases de objetos se pueden usar como nuevos tipos, por
lo tanto se pueden usar en la composicion 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 publico, de forma que los metodos publicos de A tambien
se pueden llamar sobre este campo, es decir
1 B b;
2 b.a.f(); // OK

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 281


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Composicion y la cadena de inicializacion

Hemos visto que en el constructor de la clase podemos inicializar sus


miembros en la cadena de inicializacion. En particular tambien 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 inicializacion se pueden poner tanto constructores de
subobjetos como tambien inicializar objetos built-in (int, double...) por copia.

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 282


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Herencia

Otra forma de elaborar clases mas complejas a partir de otras mas 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 metodos de A se pueden llamar ahora tambien sobre C. en este caso
estamos diciendo C es como A pero tiene algunas cosas adicionales. Al hacer
composicion estamos diciendo que C contiene a un objeto de tipo A.

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 283


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Herencia (cont.)

Notar que en el caso de composicion los miembros de A se acceden a traves


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 publico, todos los miembros y metodos de
A seran vistos a traves de C con la privacidad que tenan en A, es decir C.c es
publico 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 284


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Herencia (cont.)

Notar que con composicion 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 285


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Redefinicion de metodos

Que pasa si la clase derivada tiene un metodo con el mismo nombre que la
clase base? Con composicion 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 286


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Redefinicion de metodos (cont.)

Con herencia el nuevo metodo redefine u oculta el metodo 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 287


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Herencia protegida

Hay una forma de herencia que es intermedia entre publico y privado, y es la


herencia protected. En este caso lo metodos de la clase son privados para el
exterior pero pueden ser usados como publicos 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 288


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

18 int main() {
19 Derived d;
20 d.change(10);
21 }

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 289


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 metodo de la clase
que esta implementado en las dos, llama al de la base.
1 p->f(); // llama a Base::f()

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 290


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Polimorfismo

Nosotros queremos definir clases base que son genericas (por ejemplo
Matrix) y plantear algoritmos/operaciones genericos para las mismas (por
ejemplo GradConj()). Estos algoritmos toman un puntero a la clase base y
llaman operaciones genericas sobre la misma (por ejemplo el producto matriz
vector MatVec()). Luego podemos definir clases derivadas para las matrices
de distinto tipo (llena, banda, sparse, simetrica...) La idea es que cuando el
algoritmo generico GradConj() llama al metodo MatVec()), esta llamada sea
despachada a la funcion correspondiente en la clase derivada.

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 291


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Polimorfismo (cont.)

Para que la llamada al metodo sea despachada a la clase derivada debemos


declarar al metodo 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 292


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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.

Z xb
I1 = f (x) dx,
xa
Z yb Z xb
I2 = f (x, y) dx dy,
ya xa
Z zb Z yb Z xb
I3 = f (x, y, z) dx dy dz,
za ya xa

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 293


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 metodo eval() esta declarado =0 eso quiere decir que no se
implementara, por lo tanto es una clase virtual pura es decir que no se
pueden definir instancias de esta clase. Solo es un prototipo del cual
podremos derivar clases concretas que podran ser integradas.

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 294


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 {
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 Ingeniera y Ciencias Hdricas FICH - UNL slide 295
((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

22 cout << "Integral of sin(x) in [0,1] is "


23 << int1d.integral() << endl;
24 return 0
25 }

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 296


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 Simpsons rule
17 double integral() {
18 double
19 h = (xb-xa)/N,
20 h2 = h/2.0,
Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 297
((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 298


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Integral 2D. Version cruda

La integral doble la hacemos como composicion de dos integrales simples


Z yb Z xb 
I2 = f (x, y) dx dy,
ya xa
y
Z yb
= g(y) dy, yb g(y)
ya
Z xb y
g(y) = fy (x) dx. ya
xa
fx (y) f (x, y).
xa xb x

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 299


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Integral 2D. Version 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 300


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 301


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 302


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Integral 2D. Version 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 funcion 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 implementacion hemos hecho estas clases globales y totalmente
publicas 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 funcion g().

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 303


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Integral 2D. Version 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 304
((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 Simpsons rule
42 double integral() {
43 double
44 h = (xb-xa)/N,
45 h2 = h/2.0,
Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 305
((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 306
((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 307
((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 308
((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 309
((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 310
((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 311
((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 312
((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 313


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Integral 2D. Version 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 314
((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 315
((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 316


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 317


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 318
((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 319


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 320


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 321


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Polimorfismo: ej. suma de los elementos de un vector


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
20 class stride-t : public vector-t {
21 private:
22 int N;
Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 322
((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

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:
44 int N;
45 double p;
46 fun-t() : N(10), p(3.0) { }
Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 323
((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

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} x3 (with vecwrap): "
61 << vecsum(vw) << endl;
62

63 fun-t f;
64 cout << "sum-{j=0}{j=9} x3 (with fun-t): "
65 << vecsum(f) << endl;
66
67 return 0;
68 }

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 324


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Contenedores de la
librera STL

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 325


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

La clase vector

Inicialmente eran una serie de headers con clases desarrollado por


Hewlett Packard.
Es una librera de contenedores (vectores, listas, conjuntos, maps...) y
algoritmos (ordenamiento, filtrado, operaciones de conjuntos, eliminar
elementos duplicados...)
Estan templatizados es decir cada contenedor puede obtener objetos de
un tipo arbitrario (todos del mismo), por ejemplo vector<int>,
vector<double>.
Tambien puede contener objetos de clases definidas por el usuario
vector<A>, a condicion de que la clase A cumpla con ciertas restricciones
(por ejemplo tener un constructor por defecto, operador de asignacion
a1=a2...)
Muchos pueden anidarse, por ejemplo vector<vector<int>>.
Algunos pueden involucrar mas de un tipo, por ejemplo map<int,string>.

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 326


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

La clase vector

Emula el comportamiento de un vector estandar de C, pero se puede


redimensionar dinamicamente y libera sus recursos dinamicamente.
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 vaco

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).
v.push_front(z) inserta el elemento z al comienzo del vector (muy
ineficiente, O(n)).
z = v.front(), z = v.back() accede al primer y ultimo elemento del vector
(eficiente, O(1).
Se puede acceder a los elementos a traves de iterators
Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 327
((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

1 vector<int>::iterator q = v.begin(); // Comienzo del vector (v[0])


2 int z = *q; // Se dereferencian como ptrs
3 q++; // Incrementa al siguiente elemento
*q equivale a v[0]. Despues 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();
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++ esta sobrecargado para
la clase iterator. Igual que para enteros existe la version prefija y postfija.
Para vector tambien se puede hacer como con un vector comun
Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 328
((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

1 double sum = 0;
2 for (int j=0; j<v.size(); j++) sum += v[j];
Pero esto se puede usar solo con vector, con iteradores se puede iterar
sobre casi cualquiera de los otros contenedores.
Los iterators de vector<> soportan aritmetica de punteros (como los
punteros). Esto es solo valido para los iterators de vector, no para list<>
o map<> por ejemplo.
Se puede insertar un elemento en cualquier posicion 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 posicion 50
Despues de esto el vector tiene 101 elementos. Por supuesto esto implica
no solo redimensionar el vector sino tambien copiar los elementos en
[50,99] a [51,100].
Para pasar los vectores como argumentos conviene hacerlo a traves de
referencias para evitar la copia. Para indicar que la funcion 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 329
((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 hacerun 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 330
((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Pero sin hacer copias ni duplicados, o sea es muy eficiente.


Tambien 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-front(); // Elimina el primer elemnto (ineficiente)
4 w.pop-back(); // Elimina el ultimo elemento (eficiente)
En toda la documentacion (y en general en ciencias de la computacion) 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 asignacion:
operator= (deep copy), operator==, (comparacion por igualdad y distinto).
Para usarlo
1 #include <vector>
2 using namespace std;
Como casi todos los otros contenedores tiene bool v.isempty() (retorna
verdaderi si el contenedor esta vaco).

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 331


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 posicion entera.
Sin embargo no se puede acceder a la posicion m de la lista en forma
eficiente (es decir O(1)) ya que los elementos estan almacenados en
celdas enlazadas.
1 list<double> L;
2 // pone elementos en L. . .
3 double z = L[m]; // NO, [ ] solo para vectores
4 double z;
Solo 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 Ingeniera y Ciencias Hdricas FICH - UNL slide 332
((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

hasta encontrar la celda que apunta a q).


El interes de list<> es que permite insertar en cualquier posicion muy
eficientemente (O(1))
1 list<double> L;
2 // Pone elementos en L. . .
3 // q apunta a cualquier posicion en L
4 q = L.insert(q,w); // Inserta un nuevo elemento en el medio de la lista
insert retorna la posicion refrescada q.
1 L.insert(q,w); // deja q invalido
2 z = *q; // posible error en tiempo de ejecucion
3
4 q = L.insert(q,w); // OK refrezca q
5 z = *q; // OK!
Para borrar un elemento q = L.erase(q);, tambien 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.
Tambien se puede pasar todo un rango de una lista a otra
1 list<int> L1,L2;
2 // Pone elementos en L1, y L2
Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 333
((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

3 L1.splice(r,L2,p,q));
inserta todo el rango [p,q) de L2 en la posicion r de L1. MUY EFICIENTE
(O(1)).
list<> tambien tiene swap. De hecho swap se puede implementar para list
en terminos 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 operacion es O(1), por lo tanto es tan eficiente como swap. Pero
splice() es mas general (es como swap pero para pedazos de lista).
vector no tiene splice().
Los headers son #include <list> y <slist>

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 334


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 metodo find(x) retorna la posicion donde se encuentra un elemento
dado x, si el elemento no esta retorna S.end()
1 set<int>::iterator q = S.find(x);
2 if (q!=S.end()) {
3 // x esta en S y *q==x
4 }
find() es muy eficiente (O(log n)). Esta es la condicion de diseno de set.
Si se declara un set<A> entonces la clase A tiene que tener los requisitos
de antes (ctor por defecto, operador de asignacion). Pero ademas debe
tener sobrecargado el operator<. Esto es as ya que el find() es eficiente
porque guarda los elementos ordenados.

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 335


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

Se puede recorrer los elementos con un iterador, estan 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 posicion 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 esta o no en el conjunto. Si esta lo elimina del
conjunto y si no no hace nada. En ambos casos el valor de retorno es el
numero de elementos efectivamente eliminados, es decir 1 o 0.

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 336


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

C =AB
1 set difference(a.begin(),a.end(),b.begin(),b.end(),
-
2 inserter(c,c.begin()));
C =AB
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.
Estan en el header <algorithm>. No son metodos de la clase, son
funciones friend.
C =AB
1 C.clear();

2 set union(A.begin(),A.end(),B.begin(),B.end(),
-
3 inserter(C,C.begin()));
Notar que en principio opera sobre un rango en A y otro en B e inserta la
union de los mismos (sin elementos duplicados) en C. De la forma en que
esta llamada arriba hace la operacion estandar de union.
C =AB
1 C.clear();

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 337


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, Rodrigo Paz

2 set-difference(A.begin(),A.end(),B.begin(),B.end(),
3 inserter(C,C.begin()));
C =AB
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 Ingeniera y Ciencias Hdricas FICH - UNL slide 338


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 despues se puede
buscar las asignaciones por la clave.
Ejemplo, sueldos de los empleados
1 map<int,double> sueldos;
2 sueldos[13234567] = 23000.34;
sueldos[30245654] = 18356.34;
....
3
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 tpico
1 map<int,double>::iterator q = sueldos.begin();
Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 339
((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 mas basico 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;
Tambien se puede declarar pair<int,double> p(23,45.67);
El map tiene un efecto colateral no comun que es que si indexamos por
una clave que no tiene asignado un valor entonces crea una asginacion
poniendo como imagen el constructor por defecto de range_t
1 map<int,string> M;
2 string z = M[5]; // Asigna z= string vacio !!!

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 340


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 mas paradigmatico 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 tambien para listas
Para conjuntos no tiene sentido, ya estan 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 funcion de comparacion:
1 // Funcion de comparacion por valor absoluto
Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 341
((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))
Programacion en C++ para Ciencia e Ingeniera, por M.Storti, L. Dalcn, 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 rapido, O(n log n).

Facultad de Ingeniera y Ciencias Hdricas FICH - UNL slide 342


((version texstuff-1.2.5-48-gc81615e) (date Wed Jan 21 14:11:47 2015 -0300)
(processed-date Wed Jan 21 14:12:00 2015 -0300))

You might also like