Te anticipo, a diferencia de otros temas, en funciones me extenderé más de lo habitual, por la importancia (y amplitud) que considero tiene el tema.
La importancia de las funciones en C, en C++ y la programación en general es que son el componente fundamental que nos permite encapsular instrucciones y, tal vez más importante, son el punto de partida para poder reutilizar el código. Más aún, las funciones fueron la piedra angular sobre la que se construyeron las tecnologías orientadas a objetos.
Encapsular en términos de programación se refiere a la posibilidad de aislar segmentos de código del resto del programa, de forma que posteriormente cuando sea necesario modificar dicho código no afecte al resto del programa. Por ejemplo, considera que tenemos un programa que realiza una suma, y además, entre otras cosas, muestra el texto en color en la pantalla. De modo que sin tener que preocuparnos en este momento en cómo se hacen las dos tareas, podemos concebir nuestro programa de este modo.
int main() { SumaDeNumeros(); //Solicita los valores y los suma MuestraResultadoenColor(); //Toma el valor de SumaDeNumeros y presenta el resultado return 0; }Nota: Las sentencias de ejemplo presentadas, sí que pueden funcionar, aunque para un purista del C++ no será la mejor implementación. Pero para efectos de ilustrar el concepto, es suficiente. Recuerda prefiero claridad a información que distraiga.
Probablemente nuestro programa sume dos números, pero si posteriormente nos indican que debe sumar 10, cualquier cambio solo lo deberemos realizar dentro de SumaDeNumeros; sin preocuparnos de MuestraResultadoenColor; Por otro lado, no nos interesa como esté codificado MuestraResultadoenColor; sin embargo si podemos mejorar el código, lo haremos sin afectar (ni preocuparnos) por SumaDeNumeros;.
En términos de programación en C++ SumaDeNumeros y MuestraResultadoenColor se denominan funciones.
La encapsulación se basa en un principio básico: Una función debe contener dentro de la misma función todas las instrucciones para realizar la tarea que le ha sido asignada y los datos que debe aceptar y los resultados que debe entregar, deben controlarse y procesarse de acuerdo a la especificación de la misma función.
El objetivo de encapsular código de un programa, es aislar la lógica de un proceso en bloques independientes (funciones) con tareas especializadas para facilitar su mantenimiento y reutilización. De hecho una premisa informal es que una función debería ocuparse de la menor cantidad posible de trabajo para conservar la mayor independencia respecto a otras funciones.
Es decir lo ideal es generar funciones especializadas, tomemos nuestro ejemplo inicial.
SumaDeNumeros();Está concebida para solicitar números al usuario, realizar los cálculos y probablemente alguna validación de los datos recibidos. Puedes ver que nuestra función es “Multiusos”. Y a la hora de cambiar la cantidad de números recibidos del usuario, necesariamente debemos de cambiar el código para hacer la suma. Una solución a esto sería “especializar” nuestra función:
Presentación(); SolicitarNumeros(); SumarNumeros();Nota: No hemos visto la sintaxis de una función, así que insisto, en este momento no cuestiones la sintaxis, centrémonos en la idea expuesta
Como puedes apreciar, a SumarNúmeros no le importa cuántos ni cómo pidas los números, basta tomar de forma correcta la información que entrega SolicitarNumeros. Y Si eventualmente quieres poner, cambiar o modificar la cabecera del programa, solo tenemos que tocar Presentacion() sin preocuparnos demasiado en las demás.
Tan importante como la encapsulación de instrucciones es la reutilización de código, esta reutilización de código se refiere a la capacidad de tomar funciones ya programadas y verificadas de modo que cuando queramos realizar una tarea, simplemente “llamemos” (invocar) a dicha función y utilizarla.
Es momento de develar uno de los “secretos” en C++ todo es una función (bueno, en términos estrictos, son un objeto, pero mientras no veamos objetos, te pido que aceptes esta simplificación), ahora tal vez intuyas la relevancia de las funciones (y objetos)
Por ejemplo considera la instrucción “cout” que hemos utilizado ampliamente para mostrar texto en la pantalla. Primero debes saber que C++ no incluye ninguna instrucción de forma nativa (incorporada en la definición del lenguaje) para mostrar texto en la pantalla. Por lo que si no existiera cout (u otras opciones que más adelante utilizaremos) tendríamos que programar nuestra propia rutina (función) para realizar esta tarea tan aparentemente trivial. Cuando ya lo hubiéramos logrado, simplemente tendríamos que utiliza una y otra vez esta instrucción para mostrar el texto en pantalla. Este es el beneficio de reutilizar código mediante funciones.
C++ incorpora virtualmente miles de funciones que ya han sido programadas, solo es cuestión de saber cómo “llamarlas”, que tipo de “entrada” requieren y que resultado ofrecen. Esto te ahorrará horas (y errores) de programación.
La sintaxis completa de una función es:
[extern|static] <tipo_valor_retorno> [modificadores] <identificador>(<lista_parámetros>) { [sentencias] }
Sin embargo siguiendo con la filosofía de este tutorial presentaré la forma “simplificada” de definición de una función. Para definir una función en esta primera etapa lo haremos de acuerdo a la siguiente definición.
<tipo_valor_retorno><identificador>(<lista_parámetros>) { [sentencias] }en donde,
tipo_valor_retorno, tipo de dato que devuelve la función, es obligatorio identificador: nombre de la función, el programador lo define. lista_parámetros: Valores que recibe la función, puede existir o no en una función. Son opcionales. Los paréntesis siempre se ponen aunque no haya parámetros. Sentencias: Código que forma parte de la función y realizan las actividades que la función implementa.
Seguramente has observado la última línea de todos los programas que hemos realizado:
return 0;
return es la forma en que las funciones indican el resultado de haber ejecutado las instrucciones que contienen. La sentencia return tiene dos usos importantes. Primero, fuerza una salida inmediata de la función en que se encuentra. O sea, hace que la ejecución del programa vuelva al código que llamó a la función. En segundo lugar, se puede utilizar para devolver un valor.
Todas las funciones, excepto aquellas de tipo void, devuelven un valor. Este valor se especifica explícitamente en la sentencia return. Sin la sentencia return, el valor devuelto por la función queda técnicamente indefinido. Lo cual es una mala práctica.
Por otra parte, mientras una función no se declare como void, puede ser usada como operando en cualquier expresión válida de C++.(1)
Existe un tipo de funciones que no devuelven nada, ni siquiera void, son los constructores y destructores. Cuando revisemos los objetos los definiremos.
Normalmente cuando no devolvemos nada al final de una función se indica explícitamente un 0 después del identificador return, indicando de este modo que el programa termina “sin novedad”.
Es momento de definir nuestra primera función, para ello primero revisemos un programa sencillo sin funciones.
#include <iostream> using namespace std; int main() { double numero, cuadrado; cout<<"Bienvenido, este programa te permite realizar varios cálculos" << endl; cout<<"Este programa forma parte del tutorial de C++ para no informáticos" << endl; cout<<"Pudes consultarlo en http://a.ehack.info/leguaje-c-introduccion/" << endl << endl; cout<<"Cálculo del cuadrado de un número" << endl; cout<<"Escribe el número que será elevado al cuadrado:"; cin >> numero; cuadrado = numero * numero; cout << "El cuadrado de: " << numero << ", es: " << cuadrado << endl; cout<<"Gracias por utilizar nuestro programa."; return 0; }
Cierto, es un programa trivial, sin embargo nos permitirá ilustrar perfectamente la declaración y uso de funciones, tenlo presente porque lo utilizaremos de forma repetida.
Supongamos que queremos que la presentación siempre aparezca al inicio de cada cálculo que implementemos, esto representaría un problema: Tendríamos que repetir una y otras vez las líneas de la presentación. Imagina que implementamos 100 cálculos… esto haría que el programa tuviera 300 líneas con la misma presentación. Para evitar esta redundancia de código podemos definir una función con la presentación.
int Presentacion () { cout << "Bienvenido, este programa te permite realizar varios cálculos" << endl; cout << "Este programa forma parte del tutorial de C++ para no informáticos" << endl; cout << "Puedes consultarlo en http://a.ehack.info/leguaje-c-introduccion/" << endl << endl; return 0; }
Como puedes observar hemos declarado un función llamada Presentación, tal como indica la sintaxis de C++ se debe indicar el tipo de dato que devuelve la función. Si observas la función, es un programa en sí mismo, cuenta con su declaración de tipo, con identificador que define su nombre, “los paréntesis” que utilizamos en main, un cuerpo que va entre { }, y un valor de retorno.
Las funciones suelen definirse antes de main()
Para invocar (o llamar) a la función hay que nombrarla en nuestro código. Para ello basta con escribir el nombre de la función
Para llamara a nuestra función basta escribir
Presentacion();
al hacer esto, en ese punto se desplegará el texto que tiene nuestra función.
Considerando nuestro ejemplo inicial, nuestro programa queda de la siguiente forma.
// cpp_56_funciones1.cpp // Este programa forma parte del tutorial de introducción al lenguaje C++ // http://a.ehack.info/leguaje-c-introduccion/ // Se ilustra la declaración de funciones sin parámetros // 2018, Por http://about.me/carlosgbr // Versión 1 // Compilado en https://www.onlinegdb.com/online_c++_compiler #include <iostream> using namespace std; //Definimos nuestra función para desplegar información int Presentacion () //Presentación se encarga de desplegar un encabezado en texto simple { cout << "Bienvenido, este programa te permite realizar varios cálculos" << endl; cout << "Este programa forma parte del tutorial de C++ para no informáticos" << endl; cout << "Pudes consultarlo en http://a.ehack.info/leguaje-c-introduccion/" << endl << endl; return 0; } //Inicio del programa principal int main () { double numero, cuadrado; //Invocamos a la función Presentacion() Presentacion(); cout << "Cálculo del cuadrado de un número" << endl; cout << "Escribe el número que será elevado al cuadrado:"; cin >> numero; cuadrado = numero * numero; cout << "El cuadrado de: " << numero << ", es: " << cuadrado << endl; cout << "Gracias por utilizar nuestro programa."; return 0; }
Como puedes observar, primero declaramos nuestra función, y después definimos el programa en sí. Dentro de main podemos observar la línea Presentacion(), lo que ocurre en este punto es que cuando el compilador llega a esta línea, hay un cambio en la ejecución del programa, el programa principal es interrumpido y pasa el control a la función invocada. Gráficamente podemos visualizarlo de esta forma.
Tal vez te parezca innecesariamente complicado este enfoque en este momento, pero considera que nuestros programas son solo un comienzo en este momento. Ahora que ya puedes desplegar el anuncio con una sentencia sencilla, puedes hacerlo las veces que requieras, en cualquier lugar (válido) que requieras.
Habrás notado cuando llamamos a la función Presentación lo hicimos indicando los paréntesis, a pesar que están vacíos.
Presentacion();
Como revisamos en la definición, los paréntesis nos permiten “pasarle” valores (parámetros) a una función. O bien no hacerlo, como en nuestro caso. Cuando no pasamos ningún parámetro, entonces debemos dejar vacíos los paréntesis, sin embargo los paréntesis son obligatorios y se deben poner. En este caso decimos que nuestra función es una función sin parámetros. Este tipo de funciones simplemente realiza su trabajo, termina, y devuelve el control al programa que la llamó.
Lo más común al utilizar funciones es “pasarles” parámetros al momento de invocarlas, esto es, se le da información para realizar una tarea con esa información. La información que acepta una función depende de cómo se haya definido dicha función. revisemos nuevamente la sintaxis de declaración de una función.
[extern|static] <tipo_valor_retorno> [modificadores] <identificador>(<lista_parámetros>) { [sentencias] }
En este caso <lista_parámetros> define los valores (parámetros) que aceptará la función. Consideremos nuestro programa, realiza una operación que eleva al cuadrado un número. No nos interesa que el usuario se preocupe (o vea) cómo hacemos el cálculo. Por tanto deseamos que el cálculo se realice en una función independiente, por lo que definimos una función para que realice esta tarea:
double ElevaCuadrado(double valor) { return valor * valor; }
Como puedes observar, debemos indicar en el paréntesis el valor que aceptará la función, así como el tipo de dato de dicho valor, el cual puede ser alguno definido por C++ o definido por el usuario. Como el cálculo es muy simple, devolvemos el resultado directamente en la sentencia return, aunque nada nos impediría en implementarlo de esta forma, por ejemplo:
double ElevaCuadrado(double valor) { duble calculo; calculo = valor * valor; return calculo; }
Las dos funciones hacen lo mismo, aunque la segunda consume más recursos de procesador y más memoria.
Para invocar a nuestra función, debemos utilizar su identificador (nombre) y el (o los) parámetros que requiere.
ElevaCuadrado(5);
Dará como resultado: 25, ya dependerá como le “damos” el 5 a la función, puede ser directo como en el ejemplo, puede ser a través de una variable, etc.
Ahora implementemos estos cambios en nuestro programa inicial.
// eb57_funciones3.cpp // Este programa forma parte del tutorial de introducción al lenguaje C++ // http://a.ehack.info/leguaje-c-introduccion/ // Se ilustra el uso de parámetros variables en una función // 2018, Por http://about.me/carlosgbr // Versión 1 // Compilado en https://www.onlinegdb.com/online_c++_compiler #include <iostream> #include <stdarg.h> // Necesaria para utilizar va_list, va_start, va_arg, va_end using namespace std; float Promedio(int calificacion, ...) // Los ... indican que son parC!metros variables { float sumaCalif = 0; int cuenta = 0; int indice = calificacion; // C-dice = calificacion para determinar un punto // para determinar cuando es el C:ltimo valor. va_list marcador; // Definimos a marcador como lista variable va_start(marcador, calificacion); // Asignamos el argumento al puntero marcador while (indice != -1){ sumaCalif += indice; cuenta++; indice = va_arg(marcador,int); //recuperamos el valor actual de marcador // le asignamos tipo } va_end (marcador); // Terminamos la lista variable return sumaCalif; } int main() { cout << "La suma de boletas entregadas es: " << Promedio(1,2,3,9,-1) << endl; cout << "La suma de boletas entregadas es: " << Promedio(6, 8, 9, 10, 4, 7, 9,-1) << endl; cout << "La suma de boletas entregadas es: " << Promedio(10, 7,-1) << endl; cout << "La suma de boletas entregadas es: " << Promedio(10, 10, 0,-1) << endl; return 0; }
Al ejecutarlo verás que la salida es la misma, y probablemente seguirás pensando que es mucho trabajo para obtener lo mismo, pronto verás que no es así.
Las funciones son tan importante que dedicaremos varias lecciones analizándolas
En la siguiente lección elaboraremos algunos programas con funciones con los conceptos que hemos revisado y comentaré las parte que tengan mayor relevancia. Aunque en este momento ya conoces lo que todos te enseñan cuando te muestran este tema. Claro nosotros vamos por mucho más.
Funciones en C++ by Roberto C. González is licensed under a Creative Commons Reconocimiento-NoComercial-CompartirIgual 4.0 Internacional License.
El comando dnsenum es una herramienta de línea de comandos para realizar enumeración de DNS…
En esta entrada te presento 24 de las listas negras más comunes que los servidores…
ZoomIt es una herramienta de anotación y zoom de pantalla para presentaciones técnicas que incluyen…
WinObj es el visor de espacios de nombres de Object Manager definitivo. Es la primera…
Whois realiza el registro de registro para el nombre de dominio o la dirección IP…
VolumeID – Esta utilidad, le permite cambiar los identificadores de los discos FAT y NTFS…