Cuando empezamos a aprender a programar, uno de los primeros retos no es escribir código, sino entender cómo piensa un ordenador. A diferencia de las personas, las máquinas necesitan instrucciones claras, ordenadas y sin ambigüedades. Aquí es donde entran en juego dos conceptos fundamentales: la lógica de programación y las funciones.
Dominar estos dos pilares es imprescindible para cualquier desarrollador. Una función es un bloque de código que realiza alguna operación. También se puede describir como un “segmento” o “fracción” de programa que realiza determinadas tareas bien definidas. Su objetivo es organizar el programa, evitar repeticiones y facilitar el mantenimiento del código.
Las funciones son útiles para encapsular las operaciones comunes en un solo bloque reutilizable, idealmente con un nombre que describa claramente lo que hace la función. La función puede ser invocada, o llamada, desde cualquier lugar del programa. Cuando se accede a una función desde alguna determinada parte del programa (cuando se «llama» a una función), se ejecutan las instrucciones de que consta.
No hay ningún límite práctico para la longitud de la función, pero el buen diseño tiene como objetivo las funciones que realizan una sola tarea bien definida. Las funciones definidas en el ámbito de clase se denominan funciones miembro. En C++, a diferencia de otros lenguajes, una función también puede definirse en el ámbito de espacio de nombres (incluido el espacio de nombres global implícito).
Características Esenciales de una Función
Una función posee las siguientes características principales:
Lea también: ¿Qué es el Acuse de Recibo de la Declaración?
- Nombre: Debe tener un nombre único, con ese nombre se manda llamar en cualquier parte del código del programa y se ejecuta la tarea para qué es creada. El nombre de una función sigue las reglas para crear los nombres de variables en C, y el tipo de dato puede ser cualquiera (entero, real, carácter o arreglo) y el nombre debe seguir la notación CamelCase.
- Independiente: Ejecuta sus sentencias de código sin interferir con código de otras partes del programa.
- Regresar un valor al código que hace su llamada: Al hacer la llamada, la función ejecuta sus sentencias y si el programador lo necesita regresa el valor. En principio todas las funciones devuelven por defecto un valor entero.
- Parámetros: Las funciones admiten parámetros (argumentos), los argumentos son datos que se pasan a la función.
Declaración de una Función
Al igual que con el uso de variables, la función debe declararse antes del lugar de donde se define. Declarar una función consiste en especificar el tipo de dato que va a regresar a la función. En la declaración se debe especificar el tipo y el número de argumentos.
Una declaración de función mínima consta del tipo de valor devuelto, el nombre de la función y la lista de parámetros (que puede estar vacío), junto con palabras clave opcionales que proporcionan más instrucciones al compilador. La declaración avisa al compilador que la función existe y que se definirá después.
Una declaración de función seguida de un punto y coma puede aparecer en varios lugares de un programa. Debe aparecer antes de cualquier llamada a esa función en cada unidad de traducción. El compilador C revisa que las funciones estén definidas o declaradas antes de ser invocadas. Por lo que una buena práctica es declarar todas las funciones al inicio del programa.
Sintaxis de Declaración
La sintaxis general para declarar una función es:
tipo_de_dato nombre_funcion (tipo_de_dato argumentos);
Lea también: Usos del RFC Genérico en México
Por ejemplo:
char funcion_delcaracion (int numero, char caracter);
Esta expresión declara una función que devuelve un carácter y contiene dos argumentos.
Definición de una Función
Una definición de función consiste en la declaración y el cuerpo de la función, encerrado entre llaves, que contiene declaraciones de variables, sentencias y expresiones. El bloque de código de la función es una instrucción compuesta que define las acciones que debe realizar ésta. Se suele llamar a esta instrucción compuesta cuerpo de la función. Como cualquier otra instrucción compuesta, puede contener instrucciones de expresión, otras instrucciones compuestas, instrucciones de control, etc. Una función puede acceder a otras funciones.
Sintaxis General de Definición de una Función
La sintaxis general para la definición de una función es la siguiente:
Lea también: Su Identificación Fiscal
tipo_de_dato nombre_funcion (tipo_de_argumento argumento1, tipo_de_argumento argumento2, . . . , tipo_de_argumento argumento_n) {
definición de variables locales;
sentencias;
return;
}
Donde:
- tipo_de_dato: Tipo de dato devuelto por la función. El tipo de dato de retorno puede ser omitido, por default devuelve un entero.
- nombre_funcion: El nombre con que se identifica la función para mandarla llamar.
- tipo_de_argumento: Listado de variables, que conforman los datos que se pasarán a la función.
- sentencias: Estructura de código que ejecutará una tarea específica.
- return: Instrucción para devolver un valor.
Parámetros y Argumentos
Una función puede definir opcionalmente parámetros de entrada que permiten a los llamadores pasar argumentos a la función. Una función tiene una lista de parámetros separados por comas de cero o más tipos, cada uno de los cuales tiene un nombre mediante el cual se puede acceder a ellos dentro del cuerpo de la función. Los nombres de los parámetros no necesariamente deben ser iguales a los que se encuentran en la definición de la función.
De forma predeterminada, los argumentos se pasan a la función por valor, lo que significa que la función recibe una copia del objeto que se pasa. En el caso de objetos grandes, la realización de una copia puede ser costosa y no siempre es necesaria. Cuando una función modifica un argumento que se pasa por referencia, modifica el objeto original, no una copia local.
Una función declarada con la palabra clave única void en la lista de declaración de parámetros no toma argumentos, siempre que la palabra clave void sea el primer y único miembro de la lista de declaración de argumentos. Los argumentos del tipo void en otra parte de la lista producen errores.
Valores de Retorno y Tipos de Retorno
El tipo de retorno de una función indica el tipo de dato que va a regresar la función al terminar el bloque de código de la misma. El tipo de retorno especifica el tipo del valor que devuelve la función, o void si no se devuelve ningún valor.
Además, en el cuerpo de la función se debe incluir una o más instrucciones return para devolver un valor al punto de llamada. La expresión es opcional. Para devolver un valor determinado se utiliza la expresión return; y enseguida se escribe el valor de retorno.
En Lenguaje C se pueden devolver valores del tipo escalares. Los datos escalares, se les llama escalares a los tipos de datos int, char, long, float o double. No se pueden devolver arrays o estructuras. Se puede definir una función que no regrese un valor usando el tipo de retorno void. Una función no puede devolver otra función, o una matriz incorporada; sin embargo, puede devolver punteros a estos tipos, o una lambda, que produce un objeto de función.
En C++11, auto es un tipo de retorno válido que indica al compilador que infiera el tipo de la sentencia de retorno. En C++14, decltype(auto) también está permitido. En C++14, se puede usar auto para indicar al compilador que deduzca el tipo de retorno del cuerpo de la función sin tener que proporcionar un tipo de retorno al final. Tenga en cuenta que auto siempre se deduce a un retorno por valor y no conserva la const-ness del tipo que deduce. Para las funciones de reenvío cuyo valor de retorno necesita preservar como const o referencia de sus argumentos, puede usar la palabra clave decltype(auto), que usa las reglas de inferencia de tipos de decltype y preserva toda la información de tipos.
Un tipo de valor devuelto "normal" se encuentra en el lado izquierdo de la firma de función. Un tipo de valor devuelto final se encuentra en el lado derecho de la firma y va precedido por el -> operador.
Variables Locales
Las variables declaradas dentro del cuerpo se denominan variables locales. Una variable que se declara dentro del cuerpo de una función se llama variable local o simplemente local. Las variables locales no estáticas solo son visibles dentro del cuerpo de la función y, si se declaran en la pila, salen del ámbito cuando se cierra la función.
Cuando se construye una variable local y se devuelve por valor, el compilador suele realizar la optimización del valor de retorno con nombre para evitar operaciones de copia innecesarias. En C++, una variable local se puede declarar como estática. La variable solo es visible dentro del cuerpo de la función, pero existe una copia única de la variable para todas las instancias de la función. Los objetos estáticos locales se destruyen durante la finalización especificada por atexit.
Conceptos Avanzados y Modificadores de Función (C++)
Los lenguajes como C++ ofrecen funcionalidades adicionales para las funciones:
- Sobrecarga de funciones: Las funciones pueden ser sobrecargadas, lo que significa que diferentes versiones de una función pueden compartir el mismo nombre si difieren por el número y/o tipo de parámetros formales.
- Funciones miembro y modificadores: El nombre de la función debe comenzar con una letra o un carácter de subrayado y no puede contener espacios.
- const: Puede declarar una función miembro como const para especificar que la función no puede cambiar los valores de los miembros de datos de la clase. Al declarar una función miembro como const, se ayuda al compilador a imponer la const-corrección. Si alguien intenta por error modificar el objeto utilizando una función declarada como const, se produce un error del compilador.
- constexpr: Declarar una función como constexpr cuando el valor que produce puede ser determinado en tiempo de compilación. Una función constexpr generalmente se ejecuta más rápido que una función regular.
- inline: Que indica al compilador que reemplace todas las llamadas a la función por el propio código de función.
- noexcept: Una expresión que especifica si la función puede o no lanzar una excepción.
- virtual: (solo funciones de los miembros) Especifica que una función se puede invalidar en una clase derivada.
- override: (solo funciones de los miembros) Significa que una función de una clase derivada reemplaza una función virtual.
- final: (solo funciones de los miembros) Significa que una función no se puede invalidar en ninguna clase derivada adicional.
- Calificador de referencia: (solo funciones miembro no estáticas) Especifica al compilador qué sobrecarga de una función debe elegir cuando el parámetro implícito del objeto (*this) es una referencia rvalue frente a una referencia lvalue.
- Plantillas de Función: Una plantilla de función es parecida a una plantilla de clase; genera funciones concretas que se basan en los argumentos de plantilla. Una plantilla de función puede especificar más parámetros de tipo o valor.
- Punteros a Función: C++ admite punteros de función de la misma manera que el lenguaje C. Se recomienda usar typedef para declarar un alias para el tipo de puntero de función si declara una función que devuelve un tipo de puntero de función.
- Devolución de múltiples valores: Además de utilizar el valor de retorno en sí mismo, se puede "devolver" valores definiendo cualquier número de parámetros para utilizar el paso por referencia de manera que la función pueda modificar o inicializar los valores de los objetos que el autor de la llamada proporciona. También se pueden encapsular los valores en una clase u objeto struct con nombre. En Visual Studio 2017 versión 15.3 y posterior (disponible en modo /std:c++17 y posterior), se pueden utilizar enlaces estructurados. La ventaja de los enlaces estructurados es que las variables que almacenan los valores devueltos se inicializan al mismo tiempo que se declaran, lo que en algunos casos puede ser significativamente más eficaz.
Ejemplos Prácticos de Funciones en C
A continuación, se presentan algunos ejemplos de declaración y definición de funciones en Lenguaje C para ilustrar los conceptos abordados.
Ejemplo de Declaración de Función
Aquí se muestra un ejemplo de cómo se declara una función antes de su definición y uso en main:
#include <stdio.h>
char letrero(int num, char caracter);
main(){
char argumentos;
argumentos = letrero( 87, 'x');
return;
}
char letrero(int num, char caracter){
printf("%d, %c\n", num, caracter);
return caracter;
}
Ejemplo de Función sin Argumentos y sin Devolución de Valor
Este ejemplo demuestra una función que realiza una tarea específica sin recibir datos externos ni devolver un valor al programa que la llama:
#include <stdio.h>
#include <conio.h>
#include <math.h>
void potencia();
main(){
