martes, 2 de julio de 2013

Aprende C++: Una ojeada a las funciones

Una función es una secuencia de declaraciones diseñadas para un trabajo en particular. Ya debes saber que todo programa debe tener una función llamada main(). Aunque la mayoría del os programas tienen diversas funciones que trabajan junto con main.

En ocasiones, tu programa necesita interrumpir qué está haciendo para temporalmente hacer otra cosa. Haces esto en tu vida diaria constantemente. Por ejemplo, puedes estar leyendo un libro cuando de repente te acuerdas de que tienes que hacer una llamada. Pones un marcador en tu libro y haces la llamada, cuando terminas de llamar, vuelves a tu libro por donde lo dejaste.

Los programas en C++ trabajan de la misma manera. Un programa estará ejecutando declaraciones secuencialmente dentro de una función cuando encuentra una llamada a otra función. Una llamada de una función es una expresión que le dice a la CPU que interrumpa la función actual y que ejecute otra. La CPU "pone un marcador" en el punto exacto de la ejecución y entonces llama (ejecuta) la función nombrada en la llamada de la función. Cuando termina, la CPU vuelve al punto donde dejó el marcador y reanuda la ejecución.

Aquí un ejemplo de un programa que muestra cómo nuevas funciones son declaradas y llamadas:

// #include "stdafx.h" // sólo usuarios de Visual Studio
#include <iostream>

// Declaración de la función Imprimir()
void Imprimir()
{
     using namespace std; // lo necesitamos en cada función que use cout y cin
     cout << "Dentro de Imprimir()" << endl;
}

// Declaración de main
int main()
{
     using namespace std;
     cout << "Iniciando main()" << endl;
     Imprimir(); // esta es una llamada a la función Imprimir()
     cout << "Terminando main()" << endl;
     return 0;
}

Este programa mostrará en pantalla lo siguiente:

Iniciando main()
Dentro de Imprimir()
Terminando main()

Este programa empieza ejecutando main(), y la primera línea que es ejecutada imprime Iniciando main(). La segunda línea de main es la llamada a la función Imprimir(). En este punto, la ejecución de la declaración main(9 se suspende, y la CPU salta a Imprimir(). La primera (y única) línea de Imprimir imprime Dentro de Imprimir(). Cuando Imprimir() finaliza, el llamador (main()) reanuda su ejecución donde lo había dejado. Consecuentemente, la siguiente declaración se ejecuta. Terminando main().

Las funciones pueden ser llamadas en múltiples líneas:

// #include "stdafx.h" // sólo usuarios de Visual Studio
#include <iostream>

// Declaración de la función Imprimir()
void Imprimir()
{
     using namespace std; // lo necesitamos en cada función que use cout y cin
     cout << "Dentro de Imprimir()" << endl;
}

// Declaración de main
int main()
{
     using namespace std;
     cout << "Iniciando main()" << endl;
     Imprimir(); // esta es una llamada a la función Imprimir()
     Imprimir(); // esta es una llamada a la función Imprimir()
     Imprimir(); // esta es una llamada a la función Imprimir() 
     cout << "Terminando main()" << endl;
     return 0;
}

Este programa produce muestra lo siguiente en pantalla:

Iniciando main()
Dentro de Imprimir()
Dentro de Imprimir()
Dentro de Imprimir() 
Terminando main()

En este caso, main() es interrumpida 3 veces, una por cada llamada de Imprimir().

main() no es la única función que puede llamar a otras funciones. En el siguiente ejemplo, la función Imprimir() llama a una segunda función, llamada Imrpimir2().

// #include "stdafx.h" // sólo usuarios de Visual Studio
#include <iostream>

void Imprimir()
{
     using namespace std;
     cout << "Dentro de Imprimir2()" << endl;
}


// Declaración de la función Imprimir()
void Imprimir()
{
     using namespace std; // lo necesitamos en cada función que use cout y cin
     cout << "Iniciando Imprimir()" << endl;
     Imprimir2(); // esta es una llamada a la función Imprimir2()
     cout << "Terminando Imprimir()" << endl;
}

// Declaración de main
int main()
{
     using namespace std;
     cout << "Iniciando main()" << endl;
     Imprimir(); // esta es una llamada a la función Imprimir()
     cout << "Terminando main()" << endl;
     return 0;
}

Este programa produce lo siguiente:

Iniciando main()
Iniciando Imprimir()
Dentro de Imprimir2()
Terminando Imprimir()
Terminando main()

Valores return

 

Si te acuerdas, cuando main termina de ejecutar, devuelve un valor al sistema operativo usando una declaración return. Las funciones que escribes pueden devolver un valor a sus llamadores también. Lo hacemos cambiando el tipo de return en la declaración de la función. Un return de tipo void significa que la función no devuelve ningún valor. Un tipo de return int significa que la función devuelve un número entero.

// void significa que la función no devuelve ningún valor
void NoDevuelveNada()
{
     // Esta función no devuelve ningún valor
}

// int significa que la función devuelve un valor entero
int Devuelve5()
{
    return 5;
}

Vamos a usar estas funciones en un programa:

cout << Devuelve5(); // Imprime 5 en la pantalla
cout << Devuelve5() + 2; // Imprime 7
cout << NoDevuelveNada(); // Esto no va a compilar

En la primera declaración, Devuelve5() es ejecutada. Esta función devuelve el valor 5 a su llamador, que pasa el valor a cout.

En la segunda declaración, Devuelve5() es ejecutada y devuelve el valor 5 a su llamador- La expresión 5+2 equivale entonces a 7. El valor 7 pasa a cout.

En la tercera declaración, NoDevuelveNada() devuelve un void. Esto no es válido para pasarlo a cout y el compilador te dará un error si tratas de compilar esta línea.

Una pregunta frecuente es: "¿Mis funciones pueden devolver múltiples valores usando una declaración return?". La respuesta es no. Las funciones solo pueden devolver un único valor. Aunque hay varias maneras de trabajar sobre este problema, lo discutiremos cuando hayamos hablado en profundidad sobre las funciones.

Volviendo a main

 

Ahora ya tienes las herramientas conceptuales para entender como main() realmente funciona. Cuando el programa es ejecutado, el sistema operativo hace una llamada a la función main(). La ejecución entonces salta a la parte de arriba de main. las declaraciones son ejecutadas secuencialmente. Finalmente, main devuelve un valor entero (normalmente 0) al sistema operativo. Por eso main es declarada como int main().

Algunos compiladores te dejarán que declares main como void. Técnicamente esto es ilegal. Cuando esos compiladores ven void main(), ellos lo interpretan como

int main()
{
    // tu código aquí
    return 0;
}

Siempre deberías declarar main como int y debería devolver 0 (u otro número si hubiese un error).

Parámetros

 

Has aprendido que las funciones pueden devolver un valor al llamador. Los parámetros se usan para permitir al llamador pasar una información a la función. Esto permite a las funciones ser escritas para hacer una tarea genérica sin tener que preocuparse mucho sobre los valores que usarán. y deja esos valores para que los decida el llamador.

En este caso se entiende mucho mejor con un ejemplo. Aquí un ejemplo de una función muy simple que suma dos números y devuelve el valor al llamador.

// #include "stdafx.h" // Solo usuarios de Visual Studio
#include <iostream>

// Suma() usa dos enteros (int) como parámetros y devuelve el resultado
// a Suma() no le importa qué valores exactos toman x e y
int Suma(int x, int y)
{
     return x+y;
}

int main()
{
    using namespace std;
    // El llamador de Suma() es el que decide los valores de x e y
    cout << Suma(4, 5) << endl; // x=4, y=5 son los parámetros
    return 0;
}

Cuando la función Suma() es llamada, a x se le asigna el valor 4 y a y se le asigna el valor 5. La función equivale a 4+5, que es 9 y devuelve ese valor a main. Este valor 9 entonces, se imprime en la pantalla.

Usando funciones efectivamente

 

Uno de los grandes retos que un nuevo programador encuentra (aparte de aprender el lenguaje) es aprender cuando y cómo usar las funciones de una manera efectiva. Las funciones ofrece una gran manera de dividir tu programa en partes más manejables y reutilizables, que pueden ser fácilmente conectadas para cumplir una tarea más grande y compleja. Dividir tu programa en partes más pequeñas la complejidad de tu programa se reduce, que lo hace más fácil de modificar y escribir.

Normalmente, cuando estás aprendiendo C++, escribirás programas que envuelven 3 subtareas:
  1. Leer información introducida por el usuario
  2. Calcular valores de esa información.
  3. Imprimir el valor calculado.
 Para programas simples, leer información introducida por el usuario puede ser generalmente hecha en main(). Aunque el paso 2 podría ser un buen candidato para una función. esta función debería usar la información del usuario como parámetros y devolver el valor calculado. El valor calculado entonces podría ser imprimido (con otra función o directamente desde main()).

Una buena regla sería que cada función debería cumplir una única tarea. Algunos nuevos programadores escriben funciones que combinan 2 o 3 pasos juntos. Debido a que calcular e imprimir un valor son diferentes tareas, esto violaría esta regla. Lo ideal es que una función que calcula un valor, debería devolver este valor al llamador y dejar que éste decida qué hacer con el resultado.

No hay comentarios:

Publicar un comentario