Documentos de Académico
Documentos de Profesional
Documentos de Cultura
O R IEN TA D A A O B JETO S
(IPO O )
void ir_hasta(intx,inty);
AG B 4
Paso de argumentos a funciones
■ Diferenciemos entre:
– Lo que queremos hacer (semántica)
– Como hacerlo (mecanismos o sintaxis)
AG B 5
Paso de argumentos a funciones
■ Hay 3 tipos de semántica en los argumentos de las
funciones:
– Argumento de entrada: la función recibe el argumento
pero:
■ No puede alterarlo.
■ Recibe un duplicado, de modo que aunque lo altere, no se altera
el original.
– Argumento de salida: la función devuelve un argumento.
– Argumento de entrada-salida: la función recibe un
argumento, lo modifica y lo devuelve.
AG B 6
Paso de argumentos a funciones
■ En lenguaje C++ el paso de parámetros se efectúa
con la siguiente sintaxis:
– Los argumentos de entrada y de entrada-salida se
especifican justo después del nombre de la función,
encerrados en un único paréntesis, y separados por
comas. Eso es lo que se llama la lista de argumentos de
la función. Para cada argumento hay que especificar su
nombre (arbitrario) precedido de su correspondiente tipo.
// Retorna si se quemó:
bool Pollo::guisar(int kilos, int gramos_sal, double minutos);
AG B 8
Paso de argumentos por valor
■ Sintaxis del mecanismo “por valor”:
int main()
void Pollo::guisar(double tiempo)
{ horas 1.5
{
Pollo pollo; tiem po 1.5
while(tiempo-- > 0)
double horas = 1.5; 0.5
...
pollo.guisar(horas); -0.5
}
...
}
■ Se saca un duplicado del dato, es decir:
– Se crea una nueva variable tiempo, cuyo ámbito es la función
Pollo::guisar. (Mientras que el ámbito de horas es hasta el final de main)
– Se copia el valor de la variable inicial horas a la nueva variable tiempo.
– Son dos variables distintas e independientes. Sus ámbitos también son
distintos. Si se altera el valor de tiempo, no le afecta para nada a horas.
■ Por ello, este mecanismo de “paso por valor” se emplea para
datos de entrada. AG B 9
Paso de argumentos por referencia
■ Sintaxis del mecanismo “por referencia” (alias):
int main()
void Lavadora::encoger(int & valor)
{
{
Lavadora lavadora;
valor--;
int tallaRopa = 43;
}
lavadora.encoger(tallaRopa); Asíse declara
} la referencia valor
tallaR opa 43 valor
42
■ Ahora el dato es común a ambos ámbitos. El proceso es:
– Se crea un nuevo nombre (valor) para la variable tallaRopa.
– Los ámbitos de los nombre son distintos, pero se refieren a la misma
variable. Por ello, al decrementar valor, queda automáticamente
decrementado tallaRopa.
– valor debe llevar delante un &, en la declaración de la función.
■ Por ello, este mecanismo de “paso por referencia” se emplea
para datos de entrada-salida.AG B 10
Paso de argumentos por puntero
■ Sintaxis del mecanismo “por puntero” (dirección de
memoria o metáfora de la piola):
int main()
void Lavadora::encoger(int * valor)
{
{
Lavadora lavadora;
(*valor)--;
int tallaRopa = 43;
}
lavadora.encoger(& tallaRopa); Asíse declara
} elpuntero valor
Asíse usa elpuntero valor,
Asíse am arra elpuntero valor
para accederaldato que hay
aldato tallaR opa
alotro extrem o de la piola
AG B 11
Sintaxis de los punteros
■ Se puede acceder al dato tallaRopa desde los dos ámbitos:
main posee el dato, mientras que Lavadora::encoger
mantiene una piola amarrada a ese dato.
■ La sintaxis de los punteros es bastante complicada:
– Se declaran con *: int * valor;
– Se amarran al dato con &: lavadora.encoger(& tallaRopa);
– Se usan con *, para acceder al dato amarrado al otro extremo de la
piola: (*valor)--;
■ Es peligrosísimo usar un puntero sin haberlo amarrado
previamente:
int *valor; // Puntero no amarrado. Puede apuntar a cualquier sitio. PELIG R O
*valor = 5; // El 5 sobreescribe memoria que no nos pertenece. Core dump
■ Este mecanismo “por puntero” se emplea para datos de
entrada-salida.
AG B 12
Sintaxis de los punteros
■ Aparentemente los punteros hacen lo mismo que las
referencias. Sin embargo, son mas potentes, puesto que
también permiten cambiar con mucha facilidad el extremo a
donde está amarrada la piola:
double datos[100];
double *puntero = & datos[9]; // Se amarra (apunta) al dato número 9
*puntero = 0; // Pone a 0 el dato número 9
puntero++; // Pasa a apuntar al siguiente dato
*puntero = 0; // Pone a 0 el dato número 10
puntero -= 3; // Retrocede 3 posiciones
*puntero = 4; // Pone a 4 el dato número 7
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 99
datos 4 0 0
puntero
AG B 13
Otros mecanismos
■ Acabamos de ver los tres mecanismos básicos de
C++, para el paso de argumentos:
– “por valor” que sirve para lograr semántica “de entrada”.
– “por referencia” para semántica “de entrada-salida”.
– “por puntero” para semántica “de entrada-salida”.
■ Pero existen otras combinaciones, que veremos a
continuación. La mayoría se basan en el uso del
modificador const.
■ Además también veremos las diversas maneras de
retornar un valor (argumento de salida).
AG B 14
Paso de argumentos de entrada
■ Ejemplo argumentos de entrada: IPO O _5_1
– Por valor.
– Por referencia a una constante.
– Por puntero a una constante.
AG B 15
Paso de argumentos de entrada-salida
■ Ejemplo argumentos de entrada-salida: IPO O _5_1
– Por referencia.
– Por puntero.
AG B 16
Paso de argumentos de salida
IPO O _5_1
double * Loro::cuanto_pesas();
conststring * Loro::chao();
AG B 17
El argumento de salida
■ Si no hay valor de retorno, se especifica con el tipo
void.
■ El hecho de que solo se admita como máximo un
valor de retorno es para facilitar el encadenamiento
de funciones:
Cada función, al evaluarse, devuelve un argumento de
salida. Es decir, la función es equivalente a ese
argumento de salida. Ejemplo:
double y =0.5;
double x = sin(3 * abs(y - 0.7));
AG B 18
El argumento de salida
– La precedencia de los paréntesis fuerza a evaluar primero
la resta y-0.7. Su resultado de salida es -0.2. Por tanto,
es como si estuviera escrito:
double x = sin(3 * abs(-0.2));
– A continuación se evalúa la función abs(-0.2). El prototipo
de esta función es:
double abs(double);
– Ello significa que recibe un argumento de entrada (por
valor) de tipo double y retorna un argumento de salida
(por valor) de tipo double.
– El resultado de evaluar abs(-0.2) es 0.2, por lo que es
como si la expresión se hubiera reducido a:
double x = sin(3 * 0.2);
AG B 19
El argumento de salida
– La multiplicación de 3*0.2 da 0.6, por lo que la expresión
se reduce a:
double x = sin(0.6);
– Por último se ejecuta la función sin() cuyo prototipo es:
double sin(double);
– lo cual significa que recibe un argumento de entrada (por
valor) de tipo double y retorna un argumento de salida
(por valor) de tipo double.
– Finalmente la expresión queda reducida a la asignación:
double x = 0.0104717;
AG B 20
El argumento de salida
■ Problemas que hay que evitar: PELIG R O
– En el caso de argumentos de salida (y de entrada-salida) por puntero
o referencia, vigilar no se vaya a destruir el dato al terminar la función.
– Ejemplo incorrecto (el dato no existe, cuando la función termina):
AG B 21
El argumento de salida
■ Una posible solución: manejarlo como puntero: PELIG R O
#include “helado.h” #include “helado.h”
#include “fabricahelados.h”
Helado * FabricaHelados::crear()
{ int main()
Helado *unHelado = new Helado; {
return unHelado; // Aquí se FabricaHelados fabricaHelados;
// destruye el puntero unHelado, Helado*miHelado=fabricaHelados.crear();
// pero no el objeto al que (*miHelado).comer(); // OK
// apunta }
}
AG B 25
Aclaraciones acerca de punteros y
referencias
■ No es lo mismo:
– Puntero a una constante: la variable a la cual apunta no se puede cambiar.
– Puntero constante: el puntero siempre apunta a la misma variable.
■ Las referencias siempre son constantes (apuntan al mismo sitio, es decir,
son el alias de la misma variable). Y pueden apuntar a variables o a
constantes.
const int array[2] = { 5, 8 }; const int array[2] = { 5, 8 };
const int *p = &array[0]; // p apunta a una const int &r = array[0]; // r es alias
// constante // de una constante. Y siempre lo será.
p++; // OK, p apunta a array[1] r++; // Ilegal, por ser alias de const
*p = 0; // Ilegal, ya que array[1] es una r = 0; // Ilegal, por ser alias de const
// constante
int otro[2] = { 5, 8 };
int valor = 34; int &r = otro[1]; // r es alias de una
int * const q = &valor; // q es un puntero // variable
// constante r++; // OK, otro[1] = 9
(*q)++; // valor pasa a valer 35 r = 0; // OK, otro[1] = 0
q++; // Ilegal AG B 26