C++ Funciones

Enviado por jvilella el Lun, 23/09/2019 - 03:35

Requisitos:

Una función nos permite coger un conjunto de instrucciones de un código y encapsularlas con un nombre, de manera que con sólo llamar a ese nombre se ejecuten todas.

Por ejemplo:

void saluda() {
    cout << "Hola" << endl;
}

Y lo ejecutamos así:

int main() {
    saluda();
}

Las funciones se escriben siempre fuera del main() pero justo antes de él (debajo de todos los “#include” y del “using namespace std”). Veamos el código completo:

#include <iostream>
using namespace std;
void saluda() {
    cout << "Hola" << endl;
}
int main() {
    saluda();
}

Podría ser que quisiéramos preguntarle alguna cosa a la función. Por ejemplo, queremos saber cual es la edad del usuario y queremos pedirle esta información a la función:

int pide_edad() {
    cout << “Escribe tu edad: ” << endl;
    int edad;
    cin >> edad;
    return edad;
}

Lo primero que debemos ver es que como el valor que le preguntamos a la función es un número la función se llama “int demana_edad()”, es decir, antes del nombre de la función debemos poner qué tipo de valor nos va a devolver (de que tipo será la respuesta que nos dará).

Además al final hay una instrucción “return edad;”, esto lo que hace es decir que la respuesta es el valor que haya en la variable “edad”. Una vez la ejecución llega a una instrucción “return” la función deja de ejecutarse, por lo tanto todas las instrucciones que haya después dentro de la función no se ejecutarán.

Desde el main() llamaríamos a esta función así:

int main() {
    int edad = pide_edad();
}

Por tanto una cosa que hemos de ver es que si a una función responde a una pregunta, entonces será “void” ("vacío" en inglés) el tipo que escribimos antes de su nombre, tal como vemos en el primer ejemplo, pero si la función lo que hace es responder a una pregunta (devuelve un valor con la instrucción “return”) será del tipo de la variable que devuelva (y siempre ha de devolver el mismo tipo de variable, no puede ocurrir que a veces devuelva un int y otras un string).

Las variables no se comparten entre dos funciones, cada una tiene sus propias variables y no puede ver las variables de las otras funciones. Por ejemplo, el main() no puede ver los valores de las variables de la función pide_edad() y pide_edad() no puede ver los valores de las variables de main(). Por tanto necesitan un canal para intercambiar información.

Ya hemos visto que para pasar información de la función al main() lo hacemos a través de “return” (y sólo podemos pasarle una variable). Pues para pasar un valor del main() a la función lo hacemos a través de los paréntesis de la llamada. A cada valor que se le pasa se le llama "parámetro" o "argumento". Por ejemplo:

int suma(int valor1, int valor2) {
    return valor1 + valor2;
}
int main() {
    int num1;
    int num2;
    cin >> num1;
    cin >> num2;
    cout << suma(num1, num2);
}

Aquí va un ejemplo más complejo:

#include <iostream>
using namespace std;
int opera(int num, string operacion, int num2) {
    if (operacion == "multiplica") {
        return num * num2;
    } else if (operacion == "suma") {
        return num + num2;
    }
    cout << "esta instruccion no se ejecutara nunca";
}
int main() {
    int num;
    cin >> num;
    cout << "resultado: " << opera(num, "multiplica", 2);
}

Para dejar claro que las funciones no ven las unas las variables de las otras analiza este ejemplo:

#include <iostream>
using namespace std;
int incrementa(int num) {
    num = num + 1;
    return num;
}
int main() {
    int num = 2;
    cout << "Return: " << incrementa(num);
    cout << "Y num sigue siendo: " << num;
}

Lo que ves es que la función incrementa() ha modificado el valor de num (pasa a ser 3), pero en el main() la variable num sigue siendo 2. Esto es porque, aunque se llaman igual las dos variables, la variable num de incrementa() y la variable num de main() son dos variables diferentes. De la misma manera que dos familias pueden tener una hija que se llame “María” pero no son la misma persona, simplemente se llaman igual.

Si quisiéramos que una función modificara una de la variables que le pasamos debemos poner un símbolo ampersand (&) antes del nombre de la variable en la definición de los parámetros de la función:

#include <iostream>
using namespace std;
int incrementa(int &numero) {
    numero = numero + 1;
    return numero;
}
int main() {
    int num = 2;
    cout << "Return: " << incrementa(num);
    cout << "Y num ahora es: " << num;
}

Lo que ves ahora es que la función incrementa() ha modificado el valor de numero (pasa a ser 3) y en el main() la variable num se ha visto afectada. Esto es porque en la definición de la función incrementa() hemos definido explícitamente que queremos usar la variable original que nos pasen por parámetro.

En resumen, usar funciones ofrece varias ventajas:

  • Reduce el código: Si una secuencia de instrucciones se repite varias veces en nuestro código lo podemos poner en una función y llamar a esa función cada vez que la necesitamos.
  • Mejora la mantenibilidad del código: Si tenemos una secuencia de instrucciones que se repite varias veces y lo movemos a una función, si más adelante queremos hacer una mejora o corrección a esa secuencia de instrucciones solo tendremos que hacerlo una vez, en la función (si no existiera la función tendríamos que ir a hacer la modificación en todos los puntos de nuestro código donde aparece esa secuencia de instrucciones).
  • Mejora la legibilidad del código: Cuando una secuencia de instrucciones tiene una finalidad concreta podemos ponerlas en una función y darle un nombre que deje muy claro qué hacen. Si más adelante hay que leer ese código o lo lee otra persona será más fácil entender qué hace el código leyendo el nombre de la función (si está bien elegido el nombre) que interpretando el bloque de instrucciones.
  • Permite la reusabilidad del código: Una vez tenemos una secuencia de instrucciones en una función podemos copiar y pegar esa función a otros códigos donde nos pueda ser útil.
  • Simplificación de problemas complejos o “divide y vencerás”: Cuando tenemos un problema complejo lo mejor es dividirlo en pequeños subproblemas, que al ser más pequeños serán más sencillos de analizar y solucionar. Podemos resolver cada uno de estos problemas en una función, y finalmente relacionarlos todos en el main() para resolver el problema original.
  • Facilita la verificación del código: En lugar de probar todo nuestro código a la vez podemos probar cada función individualmente, y cuando todas ya están verificadas probamos el código completo del programa. Así sabremos que los errores que detectemos no están en las secuencias de instrucciones que hay dentro de las funciones, reduciendo la cantidad de código a analizar.
Printer Friendly, PDF & Email

Añadir nuevo comentario

Texto sin formato

  • No se permiten etiquetas HTML.
  • Saltos automáticos de líneas y de párrafos.
  • Las direcciones de correos electrónicos y páginas web se convierten en enlaces automáticamente.