Continuamos revisando el tema de funciones, en la sección anterior presentamos generalidades de las funciones, es esta sección ahondaremos en sus características.
Funciones con parámetros fijos.
Anteriormente revisamos las funciones con parámetros fijos, es decir, al momento de compilar, le indicamos al compilador cuántos y de que tipo, una función recibirá los parámetros que se le pasen. De hecho es la forma más habitual de definir una función, recordemos la sintaxis.
[extern|static] <tipo_valor_retorno> [modificadores] <identificador>(<lista_parámetros>) {
[sentencias]
}
A modo de repaso definiremos un programa que utiliza funciones, a continuación desarrollamos un programa para realizar conversiones, te sugiero revisar el código, entenderlo y modificarlo.
Comentarios acerca del programa de conversión de temperaturas.
El programa no realiza (ni pretende) ninguna tarea sofisticada, pero es un punto de partida que vale la pena revisar en su estructura en general.
- Como puedes observar, puedes generar tantas funciones como sean necesarias, recuerda nuevamente, debemos empezar por definir las funciones de la forma más primitiva que nos sea posible (es decir, que resuelvan una sola tarea)
- Utiliza nombres descriptivos y fáciles de documentar, tal vez en el momento que estás escribiendo el programa recuerdes fácilmente el nombre de una función (y qué hace) pero conforme hagas programas la memoria suele traicionarnos. Más aún si alguien más va usar nuestro código, toma mayor relevancia este punto.
- Documenta ampliamente tus funciones, muchas veces verás que los comentarios suelen ser incluso más grandes que el código en sí, pero cuando pase el tiempo y mejores tus habilidades, verás que es un recurso invaluable. Muchas veces, de los comentarios se genera la documentación para tus librerías de funciones. recuerda que los comentarios no impactan en el tamaño, ni el rendimiento del programa ejecutable, así que úsalos sin remordimientos.
- Considerando el resto del programa, es importante que veas cómo utilizando funciones logramos código más limpio y fácil de leer, pues para hacer una conversión únicamente tomamos la función que requerimos y realizamos la conversión, no nos interesa ni cómo se obtiene tal o cual resultado, lo único que nos interesa es que sea correcto. Además no «ensuciamos» nuestro programa con operaciones que pueden llegar a ser muy complejas y repetitivas.
- En caso que una función no «se comporte de forma correcta», basta con dirigirnos a la misma y realizar todos los cambios que sean necesarios. Mientras respetemos la entrada de datos y la salida de los resultados, podremos utilizarla en nuestro programa sin tocarla en el código que la utiliza.
- En otros temas generales, nota que nuestro código va creciendo más y más, pero si notas, la parte que corresponde a la conversión de temperaturas es muy corta y podríamos programarla en muy pocas líneas. El código crecerá por la necesidad que tenemos de informar al usuario de forma clara y precisa de lo que hace nuestro programa, de los datos que esperamos, para presentar la información de forma más amigable, y sobre todo, por el manejo de errores que implementemos.
- Si observas gran parte del código que se duplica corresponde a la tarea de preguntar si se desea realizar otro cálculo, podríamos «ahorrarnos» decenas de líneas, pero nuestro programa perdería flexibilidad y funcionalidad, y esto se traduce en que tus usuarios perderían interés en tu programa… por muy bueno que sea.
- Finalmente este programa te sirve como repaso en el uso de diversas estructuras de control.
A continuación te presentamos el código, como siempre es importante que lo analices y entiendas. Y después hagas de todo con él. Cambia todo lo que puedas cambiar y observa los resultados.
// cpp_58__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 funciones con varios parámetros y la llamada de funciones // por otra función // 2018, Por http://about.me/carlosgbr // Versión 1 // Compilado en https://www.onlinegdb.com/online_c++_compiler #include <iostream> using namespace std; float Suma(float x, float y) { return x+y; } float Resta(float x, float y) { return x-y; } float Producto(float x, float y) { return x*y; } float Division(float x, float y) { return x/y; } float Operacion(float x, float y, char operando) { float resultado = 0; switch (operando) { case '+': { resultado = Suma(x, y); break; } case '-': { resultado = Resta(x, y); break; } case '*': { resultado = Producto(x, y); break; } case '/': { resultado = Division(x, y); break; } } return resultado; } int main() { float operando1 = 0, operando2 = 0; char operador; cout << "Este programa realiza la operación solicitada sobre 2 operandos" << endl << endl; cout << "Escribe el símbolo de la operación que deseas realizar: + - * /" << endl; cin >> operador; cout << "Escribe el primero operando: "; cin >> operando1; cout << "Escribe el segundo operando: "; cin >> operando2; cout << "El resultado de " << operando1 << " " << operador << " " << operando2 << " = " << Operacion(operando1, operando2, operador) << endl; return 0; }
Salida del programa
Cuando ejecutes el programa verás que aunque básico, ya es una unidad «autocontenida», te ofrece una descripción, te guía en su uso, te presenta un menú, controla si quieres continuar realizando más conversiones, y termina de forma controlada. Nota que el simple hecho de solo aceptar 2 entradas (S/N) requiere muchas líneas de código, aunque no sean parte de la conversión de temperaturas.
Por otra parte el programa tiene un «error» premeditado, si observas los resultados de convertir grados centígrados a Kelvin y de Kelvin a grados Centígrados, están invertidos, como puedes apreciar en la siguiente salida del programa:
- De acuerdo a nuestro programa 0 ºC son -273.15 K, lo cual es erróneo, el valor correcto es 273.15 K
- De acuerdo a nuestro programa 0 K son 273.15 ºC, lo cual es erróneo, el valor correcto es -273.15 K
En este caso es solo cuestión de poner el cálculo correcto para cada conversión y para ello solo debemos modificar la función correspondiente, no es necesario tocar el código principal, reduciendo de este modo errores potenciales de olvidar cambiar cada punto en donde se utilice nuestra función.
Realiza el cambio de código entre las funciones de ºC a K y viceversa para que ofrezcan conversiones correctas.
Funciones que llaman a otras funciones.
Nuestras funciones pueden llamar a otras funciones (de hecho desde el primer programa hemos estado llamado a varias funciones), de modo que puedes definir funciones primitivas como los bloques sobre los cuales puedes construir funciones de mayor complejidad.
En el siguiente ejemplo se ilustra una función que recibirá 3 parámetros (recuerda que nuestras funciones pueden recibir cualquier cantidad de parámetros que necesitemos). Uno de los parámetros nos indicará la operación que queremos realizar (en nuestro caso solo consideramos la suma, resta, multiplicación y división real), los otros 2 parámetros serán los operandos.
Podríamos hacer todo en una función pero para ilustrar funciones que llaman a otras funciones, lo haremos todo en funciones distintas.
En la siguiente liga puedes descargar el código completo en donde puedes revisar el código, puedes notar que las funciones «primitivas» toman 2 parámetros y nuestra función principal toma 3 parámetros de los cuales uno es de tipo distinto.
Antes de ver el código, te sugiero que intentes generar las funciones que permitan que el código principal que a continuación se muestra, funcione.
int main() { float operando1 = 0, operando2 = 0; char operador; cout << "Este programa realiza la operación solicitada sobre 2 operandos" << endl << endl; cout << "Escribe el símbolo de la operación que deseas realizar: + - * /" << endl; cin >> operador; cout << "Escribe el primero operando: "; cin >> operando1; cout << "Escribe el segundo operando: "; cin >> operando2; cout << "El resultado de " << operando1 << " " << operador << " " << operando2 << " = " << Operacion(operando1, operando2, operador) << endl; return 0; }
A continuación te muestro 2 posibles salidas del programa:
Nota: Esta es otra de las características de las funciones, puedes asignar la implementación de funciones a tu equipo de trabajo, solo definiendo la información que vas a proporcionar y el valor que deseas recibir. De modo que la implementación no afecte el desarrollo de otras partes del código.
Funciones con parámetros variables.
C++. como herencia de C nos permite pasar un número variable de parámetros a una función, de modo que no es necesario saber cuántos parámetros recibirá una función al momento de compilarla.
Para utilizar parámetros variables, es necesario tener en consideración algunos puntos importantes(1):
- Todos los parámetros que se pasan deben ser del mismo tipo.
- La declaración de una función que toma un número variable de argumentos requiere al menos un argumento de marcador de posición, incluso si no se utiliza. Si no se proporciona este argumento de marcador de posición, no existe ninguna forma de obtener acceso a los argumentos restantes.
- Cuando los argumentos de tipo char se pasan como argumentos variables, se convierten al tipo int. De igual forma, cuando los argumentos de tipo float se pasan como argumentos variables, se convierten al tipo double. Los argumentos de otros tipos están sujetos a las promociones habituales de entero y de punto flotante.
- Las macros y funciones que requieren listas de variables se declaran con puntos suspensivos (…) en la lista de argumentos. Para obtener acceso a los argumentos que pasa una lista de variables. debes utilizar las funciones va_arg, va_copy, va_end, va_start
Sintaxis para utilizar una función con parámetros variables. (2)(3)
tipo funcion (tipo last, ... );
en donde,
- tipo: Tipo de retorno de la función.
- función: Nombre de la función
- tipo last, nombre genérico de nuestra variable y su respectivo tipo de dato.
- … : obligatorios, le indican al compilador que se espera una lista variable de argumentos (parámetros)
Para poder utilizar una lista de argumentos variable C++ tienen definido en el archivo de cabecera estándar stdarg.h una serie de macros y un tipo de dato, que nos permiten gestionar las l istas de argumentos variables.
- va_list. Este tipo de dato va a albergar el puntero a las direcciones de memoria que contienen los argumentos, , se maneja a través de las macros siguientes.
- void va_start(va_list pa, last). Esta función inicializa nuestra variable de tipo va_list. Toma dos parámetros. El primero es nuestra variable de tipo va_list. El segundo es el último parámetro conocido. Lo que hace esta función (o macro) es lo antes mencionado, toma la dirección de memoria del último parámetro conocido y posiciona el búfer pasada ésta dirección.
- tipo va_arg(va_list pa, tipo). Nos devuelve el valor del siguiente parámetro variable -apuntado por el puntero pa y de tipo tipo-, que puede ser de cualquier tipo valido que pueda pasarse como argumento a una función. Además, esta macro, manipula pa haciendo que apunte al siguiente argumento de la lista para que invocaciones sucesivas devuelvan los valores del resto de argumentos.
- void va_end(va_list pa). Una vez que terminamos, hay que emplear esta macro para indicar que hemos terminado. El único parámetro es nuestro puntero va_list.
Macros, búfer, direcciones de memoria, cast, typedef, promoción, cabecera, pseudocódigo… En 2 párrafos un mundo de términos que ni en todo lo que va de este tutorial… si no estudias sistemas, te pido ignores estos términos. No los necesitarás. Pero es imprescindible, por rigor, utilizar los términos para documentar adecuadamente los parámetros variables.
Pseudocódigo para utilizar una función de parámetros variables
A continuación tienes el pseudocódigo que muestra el uso de parámetros variables en funciones.
tipo funcionVariable(tipo ultimo , ...) { va_list pa; tipo_X argumento_de_tipo_X; va_start(pa, ultimo); while (quedanArgumentos) argumento_de_tipo_X = va_arg(pa, tipo_X); va_end(pa); }
Ejemplo 1 de argumentos variables en funciones
// cpp_59_funciones4.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; }
Puedes comprobar que nuestra función recibe cualquier número de argumentos y realiza la suma de los mismos. Puedes probar mejorar el código haciendo que sea el usuario quien introduzca los números a sumar.
En los comentarios dentro del programa se realizan las observaciones que considero oportunas.
Después de los punteros, creo que este tema es el más complejo, expuesto hasta el momento. Por el perfil de este tutorial (para no programadores) dejo en este punto la exposición de parámetros variables en funciones. El objetivo es dejar señalada la existencia de este tema y una exposición inicial. Si el lector desea profundizar en el tema, antes de publicar nuestro curso para programadores, les sugiero revisar las siguientes lecturas:
- Parámetros y Argumentos en el Lenguaje de Programación C++ del Ing. Ubaldo José Bonaparte
- Argumentos variables de Fernando A. Gómez F.
- Funciones con listas de argumentos de variable (C++) de Microsoft Developer Network
- Parámetros y argumentos de Zator.com
Conclusión
Para finalizar este tema concluyo con un extracto de la obra del Ing. Ubaldo José Bonaparte (2):
“Los parámetros juegan un papel demasiado importante en los desarrollos, donde el programador haciendo el uso adecuado de los mismos, alimentará el buen hábito de controlar exhaustivamente
la persistencia y manipulación de sus variables u objetos y como consecuencia mantendrá distancia de los efectos colaterales.
En la actualidad, la programación con lenguajes como Java, J#, .Net, C# y otros, continua sobre la base de los conceptos expuestos. De modo tal que recomendamos este artículo, especialmente a principiantes que deseen manejar cuidadosamente los parámetros y argumentos.”
Si tienes alguna duda que no se responde en este documento, por favor plantea tu pregunta para poder responderte. O escribe directamente a soporte@ehack.mx
Referencias
- Por Roberto C. González para Ethical Hack
- (1) Éste párrafo toma algunas definiciones de MSDN
- (2) Éste párrafo se basa en el trabajo de Fernando A. Gómez en el tema Argumentos variables y en mayor medida del trabajo del Ing. Ubaldo José Bonaparte en el Capítulo Parámetros y Argumentos en el Lenguaje de Programación C++ para la sección de argumentos variables páginas 25 a 35
Fuente Imágenes
- «Todas las imágenes de esta sección»: by Nala Systems
Tutorial de C++ by eHack
- Volver al índice de temas del Tutorial de C++
- *** Durante todo este tutorial se repetirá: Este es un curso orientado a gente que nunca ha programado, incluso a gente ajena a la informática. Por esta razón el desarrollo puede parecer lento en ciertas etapas. Prefiero ser claro paso a paso, que hacer «pasos mágicos» como suele ocurrir cuando se enseña programación. *** También es buena idea leas esta entrada si te preguntas «Por qué C++»
Código Fuente
- El código fuente de toda la serie lo puedes descargar en nuestro repositorio en github busca los programas con el nombre del encabezado de cada programa.
- Código de esta sección
Funciones – II, por Roberto C. González. Se distribuye bajo una Licencia Creative Commons Atribución-NoComercial-CompartirIgual 4.0 Internacional.
©2025, Ethical Hack, Todos los derechos reservados sobre el contenido propio.