Programación de Computadores 6 Funciones Prof. Javier Cañas R. Universidad Técnica Federico Santa María Departamento de Informática Contenido 1 Introducción 2 Construcción de Funciones 3 Paso de Argumentos 4 Retorno de Valores 5 Prototipos 6 Recursividad 7 Sobrecarga de Funciones 8 Funciones Inline 9 Almacenamiento y Visibilidad de Variables Javier Cañas 2000 2 1 1 Introducción • Las Funciones constituyen el elemento clave de lo que se denomina abstracción en la construcción de programas • ¿Qué se entiende por abstracción? – Es una función de la mente del ser humano que permite concentrarse en aspectos fundamentales postergando detalles Javier Cañas 2000 3 Abstracción • En la forma de solucionar problemas cotidianos y por supuesto de ingeniería aplicamos el principio de abstracción. • Por ejemplo supongamos que nos enfrentamos al problema de hacer un programa para generar remuneraciones de una empresa. El principio de abstracción nos dice que los pasos que se deben dar son: – Leer horas trabajadas en el mes – Hacer cálculos – Generar cheques Javier Cañas 2000 4 2 ...Abstracción • Cada uno de los pasos: – Leer horas trabajadas en el mes – Hacer cálculos – Generar cheques Corresponde a una función que a su vez se puede seguir descomponiendo en otras funciones • En síntesis: las funciones permiten agrupar lógicamente un conjunto de sentencias mediante un nombre. Javier Cañas 2000 5 Introducción a las Funciones • Tanto la llamada programación estructurada como orientada a objetos, se basan en funciones. • Otros objetivos de las funciones, aunque menos importante, es generar código más eficiente evitando la repetición de sentencias que se encuentran en distintas partes de un programa. Javier Cañas 2000 6 3 2 Construcción de Funciones • Para visualizar en forma simple la construcción de funciones consideremos el siguiente ejemplo: – En varias partes de un programa se desea generar una línea para dar formato a datos de salida. Para esto se usa el código: for ( int j= 0; j< 45 ; j++) cout << ‘*’ ; cout << endl ; Javier Cañas 2000 7 Construcción de Funciones for ( int j= 0; j< 45 ; j++) cout << ‘*’ ; cout << endl ; • Como este código se usa repetidas veces, hemos decidido encapsularlo en una función. • ¿Qué nombre le pondremos? – Como se trata de repetir el carácter ‘*’ (estrella) le pondremos starline (línea de estrellas) Javier Cañas 2000 8 4 La Función starline void starline( ); //prototipo o declaración void main ( ) {starline ( ); // invocación } void starline ( ) // definición {for ( int j= 0; j< 45 ; j++) cout << ‘*’ ; cout << endl ;} La 1ª línea de la definición se denomina declarador Javier Cañas 2000 9 3 Paso de Argumentos • La función anterior es útil porque cada vez que quisiéramos generar en la pantalla una línea basta con invocar su nombre. • ¿Si quisiéramos escribir el carácter ‘+’ en vez de ‘*’? – Habría que generar una nueva función, posiblemente la llamaríamos plusline – ¿Hay una forma más fácil? Si: argumentos Javier Cañas 2000 10 5 Ejemplo de Paso de Argumentos Invocación con constantes void repchar( char, int ); // prototipo repchar (‘-’ , 43 ); //invocación Parámetros void repchar( char ch, int n ) { for (int j= 0 ; j< n ; j++) cout << ch; cout << endl; } Javier Cañas 2000 11 También es posible pasar variables: void main ( ) { char car ; int nc; cout<< “Ingrese carácter :” ; cin>> car; cout<< “ Ingrese número a repetir :” ; cin >> nc; repchar ( car, nc ); } Javier Cañas 2000 12 6 Conceptos : Paso por valor • La forma de pasar argumentos vista se llama paso por valor. • Las características relevantes de esta forma son: – Los argumentos pueden ser constantes o variables. – Si son variables se crea una copia en la función. Si el parámetro se cambia dentro de la función, no afecta la variable Javier Cañas 2000 13 Conceptos : Paso por valor car nc void repchar ( char ch , int n) • la función crea nuevas variables, las cuales son accesadas igual que cualquier variable dentro del cuerpo de la función Javier Cañas 2000 14 7 Paso de Estructuras • Los objetos que se pasan a una función pueden ser más complejos que los tipos simples. • El siguiente ejemplo muestra el paso de estructuras por valor Javier Cañas 2000 15 Ejemplo de Paso de Estructuras struct Distancia { int pie; float pulgada;}; void mostrar ( Distancia ); // prototipo void main ( ) { Distancia d1; .......... mostrar ( d1);} void mostrar ( Distancia dd) {cout<< dd.pie << “\’-” <<dd.pulgada <<“\”” } Javier Cañas 2000 16 8 Paso de Argumentos por Referencia • Referencia: alias o nombre diferente para una variable • Cuando el argumento es pasado por valor, la función no tiene acceso a la variable original: sólo a una copia de ella • Cuando el argumento pasa por referencia la función tiene acceso a la variable original Javier Cañas 2000 17 Ejemplo de Paso de Argumentos por Referencia void ejemplo(int&); // prototipo int x; x=7; ejemplo (x); //x cambia a 3 cout <<x; //escribe 3 void ejemplo (int& a ) { a= 3;} Javier Cañas 2000 18 9 Alias • El operador & identifica una referencia int actual; int& otro = actual; • El compilador sabe que actual tiene otro nombre: otro. Cualquier operación en cualquiera de los dos nombres tiene el mismo resultado Javier Cañas 2000 19 Observación • El paso por referencia se puede usar en PASCAL • En C se usan punteros para este propósito Javier Cañas 2000 20 10 4 Retorno de valores • Intuitivamente las funciones que utilizamos en matemáticas tienen un valor. Por ejemplo: – sen(x) – cos(3.56); • En C++ las funciones también pueden retornar un valor. Para esto se debe declarar el tipo que retorna y agregar la sentencia return en el cuerpo de la función • Veremos un ejemplo de una función que convierte pulgadas en centímetros Javier Cañas 2000 21 Ejemplo de Retorno de Valores float convertir (float pulg); float convertir (float in) { float cm = 2.53 * in; return cm; } Javier Cañas 2000 22 11 Retorno de estructuras struct Punto { float x,y; } Punto suma (Punto P1, Punto P2) { Punto p; p.x = P1.x + P2.x; p.y = P1.y + P2.y; return p;} Javier Cañas 2000 23 Síntesis de mecanismos de comunicación Paso por valor Paso por referencia Argumentos return Función Retorno de valor Javier Cañas 2000 Efecto lateral se modifican variables externas 24 12 5 Prototipos • ¿Por qué usar prototipos? – Permiten comprender sin entrar en detalles lo que hacen las distintas funciones que componen un programa • Por esto, los prototipos tienen gran importancia en el desarrollo de grandes programas • Para mayor claridad es bueno usar nombres de parámetros en los prototipos Javier Cañas 2000 25 Ejemplo de Prototipos void muestre_punto(int, int ); // prototipo void muestre_punto(int horiz,int vert ) ; pueden ser diferentes void muestre_punto ( int x, int y ) { ...... } Javier Cañas 2000 26 13 6 Recursividad • C y C++ permite que una función pueda llamarse a si misma. • Una función que se invoca a si misma se denomina función recursiva • La Recursividad permite solucionar problemas complejos que de otra manera serían casi imposibles. Un ejemplo es el problea de las “Torres de Hanoi” Javier Cañas 2000 27 Recurrencias • La recursividad permite en forma muy simple transformar a código expresiones que estén definidas por relaciones de recurrencias. • Por ejemplo, el factorial, números de Fibonacci, potencias, series etc... Javier Cañas 2000 28 14 Ejemplo: Cálculo de n! 1 n=0 n!= n × (n − 1)! n > 0 long int factorial(int n) { if (n==0) return 1; else return n*factorial(n-1)} Javier Cañas 2000 29 Ejercicio Calcular en forma recursiva: n 1 Hn = ∑ i =1 i Javier Cañas 2000 30 15 7 Sobrecarga de Funciones • Una función sobrecargada realiza acciones diferentes dependiendo de los argumentos que se le enteguen En otros lenguajes se // prototipos requiere 3 nombres distintos void repchar ( ); void repchar ( char ); void repchar ( char, int ); Javier Cañas 2000 31 Sobrecarga de Funciones void main ( ) { repchar ( ); repchar ( ‘=‘ ); repchar ( ‘+’, 25); } Javier Cañas 2000 32 16 Sobrecarga de Funciones void repchar ( ) {for (int j= 0; j< 45; j++) cout << ‘*’; cout << endl; } void repchar (char ch ) {for (int j= 0; j<45; j++) cout<< ch; cout<< endl;} void repchar (char ch, int n) {for (int j= 0; j< n ; j++) cout << ch; cout <<endl;} Javier Cañas 2000 33 Argumentos por defecto • En el prototipo se pueden especificar los argumentos por defecto void repchar( char=‘*’,int=45); main ( ) {repchar ( ) ; // 45* repchar ( ‘=‘); // 45 signos = repchar ( ‘+’ , 30); // 30 + } Javier Cañas 2000 34 17 Argumentos por defecto • También es posible incluir nombres de parámetros en el prototipo void repchar( char c= ‘x’, int n= 45); // prototipo Javier Cañas 2000 35 Sobrecarga con tipos diferentes • El compilador puede distinguir también entre funciones sobrecargadas con el mismo número de argumentos siempre que sus tipos sean diferentes Javier Cañas 2000 36 18 Sobrecarga con tipos diferentes struct Punto {float x, y;} void sumar (Punto&, Punto&); void sumar (float &, float&) void sumar (Punto& P1, Punto& P2) { P1.x += P2.x; P1. Y +=P2.y;} void sumar (float &x, float &y ) { x+= y;} Javier Cañas 2000 37 8 Funciones Inline • Similar a las macros de C (# define ). Proporcionan un mejor chequeo de tipos • Para programas cortos es más eficiente. Una llamada normal tiene un costo en tiempo • La función inline ocupa mayor espacio Javier Cañas 2000 38 19 Funciones Normales main() ... func1(); .... func1(); .... func1(); .... El código que se repite es puesto en una función func1(); Javier Cañas 2000 39 Funciones Inline main() func1(); func1(); El código que se repite es puesto en una función llamada inline func1(); Javier Cañas 2000 40 20 Ejemplo de Funciones Inline • Debe ir antes de su invocación inline float convertir (float in ) { return 2.53 * in ; } Javier Cañas 2000 41 9 Almacenamiento y Visibilidad de Variables • C++ define distintas clases de almacenamiento • Cada clase de almacenamiento determina reglas de alcance y visibilidad • Las clases de almacenamiento son: – automática: auto – externa: extern – estática: static Javier Cañas 2000 42 21 Almacenamiento Automático • • • • Se crean sólo cuando la función es llamada Se destruyen cuando la función termina ¡ Se ahorra memoria! Cuando las variables se crean el compilador no trata de iniciarlas • ¡Pueden contener basura! • ¡Limitar la visibilidad ayuda a organizar y modularizar el programa! Javier Cañas 2000 43 Ejemplo de Almacenamiento Automático void funcion ( ) { auto int x ; auto float y ; .......... } void f1 ( ) { int x; ...... } void f2 ( ) { int y; ... x= 3; /* ilegal x no es visible aquí */ . } Javier Cañas 2000 44 22 Observaciones • La palabra reservada auto se puede omitir. Se asume por defecto que las variables que se definen dentro de una función son automáticas • Limitar la visibilidad ayuda a organizar y modularizar el programa. También ayuda a prevenir errores Javier Cañas 2000 45 Almacenamiento Externo • Las variables externas se denominan también globales • Se inicializan automáticamente en cero • Se definen fuera de cualquier función • La Visibilidad de la variable es el archivo fuente completo • Es mejor usar restringídamente este tipo de variables ya que crea problemas en la organización de programas grandes Javier Cañas 2000 46 23 Ejemplo de Almacenamiento externo #include < iostream. h > int extint = 99;//var.ext. //Se inicializa en cero void f ( ); void main ( ) {.... extint = 100; /*Se tiene acceso a la variable externa*/ ....} void f ( ) { ..... extint = 3; /*también desde aquí se tiene acceso a la variable externa*/ } Javier Cañas 2000 47 Almacenamiento Estático • Existen variables estáticas externas y estáticas automáticas • Variables estáticas automáticas – visibilidad de variables automática – duración de variable externa • El siguiente ejemplo muestra la utilización de este almacenamiento en una función que permite acumular el promedio Javier Cañas 2000 48 24 Ejemplo de Almacenamiento Estático float getprom ( float nuevo_dato) {static float total= 0, static int cuenta= 0; /* Sólo se inicializan una vez por programa*/ cuenta ++; total += nuevo_dato; return total/ cuenta;} Javier Cañas 2000 49 FIN Funciones 25