El documento describe las funciones en C++. Las funciones permiten dividir un programa en partes más pequeñas y reutilizables. Pueden aceptar datos como entrada, realizar cálculos y devolver resultados. Existen tres características principales de las funciones: la definición, declaración y llamada. La definición especifica el código de la función, la declaración informa al compilador sobre la función, y la llamada invoca la función.
1. Funciones en C++
Básicamente una función puede realizar las mismas acciones que un
programa:
aceptar datos
realizar unos cálculos determinados y, finalmente,
devolver resultados
Las funciones son invocadas desde otras funciones, con una excepción: la
función global main() , que tienen todos los programas en C++. Permite al
compilador conocer donde está el punto inicial de un programa. Por razones
obvias, main() no puede ser invocada desde otras funciones.
Podemos distinguir 3 características de las funciones en C++:
la definición
la declaración
la llamada
Definición de una función
Es el código que realiza las tareas para las que la función ha sido prevista.
La primera línea de la definición recibe el nombre de encabezamiento y el
resto, un bloque encerrado entre llaves, es el cuerpo de la función.
La definición de una función se debe realizar en alguno de los ficheros que
forman parte del programa.
La sintaxis habitual de una definición de función es la siguiente
tipo nombre_funcion(tipo_1 arg_1, ..., tipo_n arg_n)
{
sentencias;
return expresion; // optativo
}
tipo : indica el tipo de valor ( int , float , etc.) devuelto por la función.
nombre_funcion : es el identificador usado para la función.
la lista de argumentos es una secuencia de declaración de
parámetros separados por comas y encerrados entre paréntesis. Son los
llamados parámetros formales de la función.
2. return expresion es un salto incondicional que permite evaluar una
expresión y devolver su valor a la función llamante.
Veamos un ejemplo de definición de función que calcula la media de dos
números reales.
Ejemplo
double calcula_media(double num1, double num2)
{
double media;
media = (num1 + num2)/2.;
return media;
}
El tipo de una función
Una función devuelve, como mucho, un único valor a través de la
sentencia return . Este valor tendrá el mismo tipo que el de la función.
La palabra reservada return permite realizar un salto incondicional, de la
misma forma que break . En este caso, devuelve desde el interior de la función
actual el control del programa a la función que la llamó.
3. La función main()
El prototipo de la función main() que usamos en la asignatura es:
int main();
Vemos que la función principal main() tiene tipo int . Sin embargo, en la
mayoría de los ejemplos no usamos return para devolver un entero.
En C++ y sólo para la función main() , si no aparece la sentencia return , el
compilador añade implícitamente return 0; al final.
En el resto de funciones que devuelven un tipo, olvidar el return causará un
comportamiento indefinido en el programa.
Utilidad del return de la función main()
Debemos tener en cuenta que, lo mismo que una función puede invocar a otra,
un programa puede ser llamado desde otro. De hecho, es lo que hacemos
desde un entorno de desarrollo como Code::Blocks invocando al compilador
C++.
En ocasiones, el programa que invoca al otro necesita saber si todo ha ido bien
o si, por el contrario, ha ocurrido un problema. Así, vía el valor entero
del return podemos establecer unos códigos que informen al programa
invocante.
Usando return 0; se asume por convención que el programa ha terminado
con éxito.
return EXIT_SUCCESS; o return EXIT_FAILURE; son otras formas de informar de
terminación sin/con errores.
Las constantes EXIT_SUCCESS y EXIT_FAILURE están definidas en la
biblioteca cstdlib .
Argumentos de la línea de comandos
La función main() también admite el prototipo:
int main(int ac, char** av);
De esta forma, desde una terminal, podemos invocar a un programa
suministrándole unos argumentos de entrada.
4. No estudiaremos esta alternativa en este curso.
Nota
C++ permite la sobrecarga de funciones, caracterizadas por compartir el
identificador, pero con diferentes listas de argumentos.
Una función puede tener varios puntos en los que se devuelve un valor
con return y, lógicamente, finalizará en el primero que se ejecute.
Al igual que con los break , la legibilidad del código debe ser la decisión que
determine que haya un único return (preferible) o varios.
Declaración de una función
Al igual que ocurre con otros identificadores, en C++ no podemos llamar a una
función en una sentencia sin que esté declarada previamente.
Una declaración explícita de una función, también denominada prototipo de la
función, tiene la expresión general:
tipo nombre_funcion(tipo_1, tipo_2, ..., tipo_n);
En el ejemplo anterior el prototipo de la función es:
double calcula_media(double, double);
Es habitual encontrar prototipos acompañados de identificadores, en aras a
mejorar la legibilidad del código. En cualquier caso es opcional. Así, el ejemplo
anterior podría programarse como:
double calcula_media(double x, double y);
Recordemos que en C++, una declaración permite al compilador:
conocer de antemano las necesidades de memoria
(se enviarán a la función dos double y se recibirá un double )
gracias al tipado estático, detectar errores en tiempo de compilación
5. por ejemplo, si utilizamos la función con argumentos cuyos tipos no son
compatibles con los explicitados en su prototipo.
LLamada a la función
La llamada a una función se hace especificando su nombre y, entre paréntesis,
las expresiones cuyos valores se van a enviar como argumentos de la función.
Estos parámetros pueden ser identificadores o cualquier otra expresión válida.
La llamada a una función se escribe de forma general como sigue:
salida = nombre_funcion(arg_1, arg_2, ..., arg_n);
En nuestro ejemplo podría ser:
double resultado = calcula_media(numero1, numero2);
o, por ejemplo:
double resultado = calcula_media(numero1+numero2, 7);
Veamos un ejemplo completo con la función calcula_media()
Ejemplo
// Cálculo de la media de dos números
#include <iostream>
using namespace std;
double calcula_media(double, double); // Declaración
int main()
{
double numero1, numero2;
cout << "Introduzca el primer número: ";
cin >> numero1;
cout << "Introduzca el segundo número: ";
cin >> numero2;
double resultado = calcula_media(numero1, numero2); // Llamada
cout << "La media de "<< numero1 << " y " << numero2
<< " es " << resultado << ".n";
}
// Definición
double calcula_media(double num1, double num2)
{
double media;
media = (num1+num2)/2.;
return media;
}
6. Edita, compila y ejecuta el código
Error debido a una función no declarada
Es muy importante entender las consecuencias derivadas de:
no declarar una función
no definir una función
En el ejemplo, comente la línea de la declaración de la función:
// double calcula_media(double, double); // Declaración
Al compilar el programa, obtendrá un error similar a:
error: use of undeclared identifier 'calcula_media'
o
error: 'calcula_media' was not declared in this scope
La razón es obvia. Todo identificador debe estar declarado antes de su uso.
Cuando el compilador analiza la línea:
double resultado = calcula_media(numero1, numero2);
desconoce qué tipo de identificador es calcula_media .
Error debido a una función no definida
En el ejemplo, comente toda la definición de la función.
//double calcula_media(double num1, double num2)
//{
// double media;
// media = (num1 + num2)/2.;
// return (media); // return media es válido también
//}
Al compilar el programa, obtendrá un error similar a:
undefined reference to `calcula_media(double, double)' , error: linker command fa
iled with exit code 1
Claramente aparece el aviso de que no está definida la función, undefined . En
realidad, el compilador ha sido capaz de generar el código objeto del archivo.
Toda la información necesaria está disponible respecto a la función main() .
7. Es el enlazador (linker) el que ha dado la voz de alarma. No encuentra un
archivo donde esté la definición de la función.
Declaración y definición simultáneas
Al igual que con las variables de tipos fundamentales, podemos optar por
declarar y definir en un mismo paso, como puede verse en el ejemplo siguiente.
// Cálculo de la media de dos números
#include <iostream>
using namespace std;
// Declaración y definición simultáneas
double calcula_media(double num1, double num2)
{
double media;
media = (num1+num2)/2.;
return (media); // return media es también válido;
}
int main()
{
double numero1, numero2;
cout << "Introduzca el primer número: ";
cin >> numero1;
cout << "Introduzca el segundo número: ";
cin >> numero2;
double resultado = calcula_media(numero1, numero2); // Llamada
cout << "La media de "<< numero1 << " y " << numero2
<< " es " << resultado << ".n";
}
Edita, compila y ejecuta el código
Funciones void
En ocasiones una función no necesita devolver ningún valor y, por tanto, no es
obligatorio usar return .
Para ello, debemos definir la función con un tipo especial llamado void .
Ejemplo
#include <iostream>
using namespace std;
void imprime_cadena(string cadena)
{
cout << cadena;
// return; // Opcional
}
int main()
8. {
string cadena = "Hola";
imprime_cadena(cadena);
imprime_cadena(" mundo.n");
}
Edita, compila y ejecuta el código
Nota
std::string es un tipo de dato no nativo del espacio de nombres std , que
permite almacenar y manipular cadenas de caracteres.
Funciones sin argumentos
Una función puede no necesitar una lista de parámetros.
Ejemplo
#include <iostream>
using namespace std;
//Opcional void imprime_mensaje_inicial(void)
void imprime_mensaje_inicial()
{
cout << "Este programa bla bla bla…n";
}
int main()
{
imprime_mensaje_inicial();
}
Fuentes
Escuela de Ingenierías Industriales (Sede Doctor Mergelina) . Universidad de
Valladolid (EII-UVa)