3 Funciones I: Declaración y definición

Las funciones son un conjunto de instrucciones que realizan una tarea específica. En general toman ciertos valores de entrada, llamados parámetros y proporcionan un valor de salida o valor de retorno; aunque en C++, tanto unos como el otro son opcionales, y pueden no existir.

Tal vez parezca un poco precipitado introducir este concepto tan pronto en el curso. Sin embargo, las funciones son una herramienta muy valiosa, y como se usan en todos los programas C++, creo que debemos tener, al menos, una primera noción de su uso. A fin de cuentas, todos los programas C++ contienen, como mínimo, una función.

Prototipos de funciones

En C++ es obligatorio usar prototipos. Un prototipo es una declaración de una función. Consiste en una presentación de la función, exactamente con la misma estructura que la definición, pero sin cuerpo y terminada con un ";". La estructura de un prototipo es:

[extern|static] <tipo_valor_retorno> [<modificadores>] <identificador>(<lista_parámetros>); 

En general, el prototipo de una función se compone de las siguientes secciones:

  • Opcionalmente, una palabra que especifique el tipo de almacenamiento, puede ser extern o static. Si no se especifica ninguna, por defecto será extern. No te preocupes de esto todavía, de momento sólo usaremos funciones externas, lo menciono porque es parte de la declaración.
  • El tipo del valor de retorno, que puede ser void, si no necesitamos valor de retorno. En C, si no se establece, será int por defecto, aunque en general se considera una mala técnica de programación omitir el tipo de valor de retorno de una función. En C++ es obligatorio indicar el tipo del valor de retorno.
  • Modificadores opcionales. Tienen un uso muy específico, de momento no entraremos en este particular, lo veremos en capítulos posteriores.
  • El identificador de la función. Es costumbre, muy útil y muy recomendable, poner nombres que indiquen, lo más claramente posible, qué es lo que hace la función, y que permitan interpretar qué hace el programa con sólo leerlos. Cuando se precisen varias palabras para conseguir este efecto se puede usar alguna de las reglas más usuales. Una consiste en separar cada palabra con un "_". Otra, que yo prefiero, consiste en escribir la primera letra de cada palabra en mayúscula y el resto en minúsculas. Por ejemplo, si hacemos una función que busque el número de teléfono de una persona en una base de datos, podríamos llamarla "busca_telefono" o "BuscaTelefono".
  • Una lista de declaraciones de parámetros entre paréntesis. Los parámetros de una función son los valores de entrada (y en ocasiones también de salida). Para la función se comportan exactamente igual que variables, y de hecho cada parámetro se declara igual que una variable. Una lista de parámetros es un conjunto de declaraciones de parámetros separados con comas. Puede tratarse de una lista vacía. En C es preferible usar la forma "func(void)" para listas de parámetros vacías. En C++ este procedimiento se considera obsoleto, se usa simplemente "func()".

Por ejemplo:

int Mayor(int a, int b);

Un prototipo sirve para indicar al compilador los tipos de retorno y los de los parámetros de una función, de modo que compruebe si son del tipo correcto cada vez que se use esta función dentro del programa, o para hacer las conversiones de tipo cuando sea necesario.

En el prototipo, los nombres de los parámetros son opcionales, y si se incluyen suele ser como documentación y ayuda en la interpretación y comprensión del programa. El ejemplo de prototipo anterior sería igualmente válido si se escribiera como:

int Mayor(int, int);

Esto sólo indica que en algún lugar del programa se definirá una función "Mayor" que admite dos parámetros de tipo int y que devolverá un valor de tipo int. No es necesario escribir nombres para los parámetros, ya que el prototipo no los usa. En otro lugar del programa habrá una definición completa de la función.

Normalmente, los prototipos de las funciones se declaran dentro del fichero del programa, o bien se incluyen desde un fichero externo, llamado fichero de cabecera, (para esto se usa la directiva #include, que veremos en el siguiente capítulo).

Ya lo hemos dicho más arriba, pero las funciones son extern por defecto. Esto quiere decir que son accesibles desde cualquier punto del programa, aunque se encuentren en otros ficheros fuente del mismo programa.

En contraposición las funciones declaradas static sólo son accesibles dentro del fichero fuente donde se definen.

Definición de funciones

Al igual que hemos visto con las variables, las funciones deben declararse, para lo que usaremos los prototipos, pero también deben definirse.

Una definición contiene además las instrucciones con las que la función realizará su trabajo, es decir, su código.

La sintaxis de una definición de función es:

[extern|static] <tipo_valor_retorno> [modificadores] <identificador>(<lista_parámetros>)
{
   [sentencias]
}

Como vemos, la sintaxis es idéntica a la del prototipo, salvo que se elimina el punto y coma final, y se añade el cuerpo de función que representa el código que será ejecutado cuando se llame a la función. El cuerpo de la función se encierra entre llaves "{}".

La definición de la función se hace más adelante o más abajo, según se mire, es decir, se hace después que el prototipo. Lo habitual es hacerlo después de la función main.

Una función muy especial es la función main, de la que ya hablamos en el capítulo primero. Se trata de la función de entrada, y debe existir siempre, ya será la que tome el control cuando se ejecute el programa. Los programas Windows usan la función WinMain como función de entrada, aunque en realidad esta función contiene en su interior la definición de una función main, pero todo esto se explica en otro lugar.

Existen reglas para el uso de los valores de retorno y de los parámetros de la función main, pero de momento la usaremos como int main() o int main(void), con un entero como valor de retorno y sin parámetros de entrada. El valor de retorno indicará si el programa ha terminado sin novedad ni errores retornando cero, cualquier otro valor de retorno indicará un código de error.

Estructura de un programa C++

La estructura de un programa en C o C++ quedaría así:

[directivas del pre-procesador: includes y defines]
[declaración de variables globales]
[prototipos de funciones]
[declaraciones de clases]
función main 
[definiciones de funciones]
[definiciones de clases]

También se puede omitir el prototipo si se hace la definición antes de cualquier llamada a la función, es decir, en la zona de declaración de prototipos. Esto se puede hacer siempre, sin embargo no es muy recomendable como veremos a lo largo del curso.

Para no dejar las cosas "a medias", podemos ver una posible definición de la función "Mayor", que podría ser la siguiente:

int Mayor(int a, int b)
{
   if(a > b) return a; else return b;
}

Estructuras más complejas

Los programas complejos se escriben normalmente usando varios ficheros fuente. Estos ficheros se compilan separadamente y se enlazan todos juntos. Esto es una gran ventaja durante el desarrollo y depuración de grandes programas, ya que las modificaciones en un fichero fuente sólo nos obligarán a compilar ese fichero fuente, y no el resto, con el consiguiente ahorro de tiempo.

La definición de las funciones y clases puede hacerse dentro de los ficheros fuente o también pueden enlazarse desde bibliotecas compiladas previamente.

En C++ es obligatorio el uso funciones prototipo, y aunque en C no lo es, resulta altamente recomendable.

Palabras reservadas usadas en este capítulo

extern y static.

Comentarios de los usuarios (29)

Esteban
2011-08-11 03:52:10

Hola.. Necesito unas preguntas, ¿Cual es la cantidad minima y maxima de parametros para una funcion? y

¿Cual es la cantidad minima y maxima de veces que puede aparecer return una funcion? y ¿ Cuando y que restrincciones tiene return?

Steven R. Davidson
2011-08-11 12:09:58

Hola Esteban,

- Como no es necesario que una función acepte parámetros, entonces la cota inferior es obviamente 0 (cero). La cota superior depende del compilador que uses. El estándar de C++ recomienda que el mínimo de esta cota superior sea de 256 parámetros. Claro está, esto es una mera recomendación.

- El vocablo 'return' aparece al comienzo de una sentencia. Por lo tanto, esta sentencia puede aparecer tantas veces como requiera la lógica de la función. Si la función retorna un valor, entonces debe aparecer al menos una sentencia 'return' y recomiendo que sea libre de condiciones. Varios compiladores se quejarán si no "ven" una sentencia 'return' "suelta", sin que dependa de condiciones como la sentencia 'if'. Por ejemplo,

int func( int a )
{
  if( a > 0 )  return 10;
  else return -10;
}

Algunos compiladores se quejarán de que no hay una sentencia 'return' garantizada a ser ejecutada. La solución en estos casos es escribir:

int func( int a )
{
  if( a > 0 )
    return 10;

  return -10;
}

Y así mantener al menos una sentencia 'return' libre de condiciones y "suelta".

En resumen, puede aparecer entre 0 (cero) e "infinitamente" muchas veces. Si la función requiere retornar un valor, entonces debe haber una sentencia 'return' como mínimo.

- Bueno, creo que he contestado a la última pregunta acerca de las restricciones de 'return' al igual que el otro matiz que preguntas.

Espero que esto te aclare las dudas.

Steven

Christian
2011-08-22 04:41:46

Tengo una pregunta...

Como hago que un arreglo pueda utilizarse en una funcion.

por ejemplo, si quiero llenar de datos el arreglo atrvés de una función, como se haria? ya que los cambios que hago al arreglo se quedan en la funcion y no en el main.

Steven R. Davidson
2011-08-22 12:36:28

Hola Christian,

La verdad es que los cambios que hagas a los elementos del array sí permanecen dentro y fuera de la función, con tal de que los elementos del array no sean tratados como constantes. Esto se explica más adelante en el capítulo 12 ( http://c.conclase.net/curso/?cap=012 ), donde veremos el vínculo entre puntero y array, y concretamente en el capítulo 15 ( http://c.conclase.net/curso/?cap=015b#FUN2_ArrayParam ) para el paso de arrays como parámetros a una función.

Espero haber aclarado un poco el tema, por ahora. No quisiera abrumarte con todos los detalles ahora mismo, porque estás empezando.

Steven

Sebastián
2011-10-02 17:29:11

Me quedo una duda. ¿Qué utilidad real tiene el uso de static? o ¿Qué ventajas y/o desventajas tiene usar static?

Me refiero a que podríamos definirlas todas como extern y simplemente no usarlas en otros ficheros. Mi duda es algo así como lo que se planteaba en la parte de variables con el tipo double y float (que en ese caso la razón era el ahorro de recurso).

Salio un poco larga la consulta, pero traté de explicarme lo mejor que pude. Muchas gracias de ante mano y muy buen curso!

Saludos!.

Steven R. Davidson
2011-10-03 16:51:02

Hola Sebastián,

Las funciones estáticas sirven a la hora de restringir su uso en un fichero fuente en particular y así no compartirlas con el resto de los ficheros fuentes. En general, las funciones sí son compartidas porque describen un comportamiento, lógica, o subprograma que normalmente se ofrece en caso de necesidad.

Sin embargo, en otras ocasiones, uno no quiere compartir algunas funciones. Puede haber varias razones, como por ejemplo, el programador quería ofrecer ciertas funciones agrupadas bajo una biblioteca para realizar una tarea en particular, pero internamente necesitaba crear y usar unas funciones auxiliares. Por lo tanto, restringe el acceso a esas funciones auxiliadoras, porque no pertenecen al juego de funciones que quiere ofrecer. Por ejemplo,

// "oper.h"

double sumar( double der, double izq );
double restar( double der, double izq );
double multiplicar( double der, double izq );
double dividir( double der, double izq );


// "oper.cpp"

// Ejecuta una instrucción de un procesador especializado 
//   para realizar cualquier operación aritmética
static double instAritmetica( unsigned int nInst, double param1, double param2 )
{
  ...
}

double sumar( double der, double izq )
{
  return instAritmetica( 1, der, izq );
}

double restar( double der, double izq )
{
  return instAritmetica( 2, der, izq );
}

double multiplicar( double der, double izq )
{
  return instAritmetica( 3, der, izq );
}

double dividir( double der, double izq )
{
  return instAritmetica( 4, der, izq );
}

De esta manera, cualquier programador tendrá acceso a las cuatro funciones aritméticas que el programador original quiso ofrecer. No se ofrece la función, 'instAritmetica()', porque no pertenece a ese conjunto de funciones creado por el programador original.

Otro ejemplo puede ser a la hora de limitar la cantidad de funciones ofrecidas siguiendo una docuemntación establecida por los diseñadores. Por ejemplo, tu jefe de proyecto te da una lista de las funciones que debes implementar, pero no te limita mucho en cuanto a la forma de implementarlas. Implementas las funciones indicadas, pero internamente, creaste unas cuantas funciones más para ayudarte en la creación de las demás. Esas otras funciones auxiliares que creaste no forman parte del cometido original, y como se limitan a un código fuente, decides usar 'static'.

Otra razón puede ser que existan coincidencias con las funciones que usas en varios ficheros fuente. Para separar una función de las otras "versiones", usas 'static' para no compartirlas y así evitar problemas de conflicto de nombres.

Espero haber aclarado la duda.

Steven

Sebastián
2011-10-03 19:10:57

Me a quedado muy claro! Muchas gracias nuevamente, gracias por la rapida respuesta y por este excelente tutorial! :D

Alvaro Garcia
2012-03-30 18:52:56

me podrias decir que comando debo de utilizar para que mi programa en consola de windows se abra de forma oculta gracias respondeme

Diego Nava
2012-05-22 21:37:26

Saludos. Tengo varias dudas respecto a funciones en c++: ¿una función puede retornar más de un valor? Si no es así, ¿que podría hacer? Es una función que guarda cadenas de caracteres de un archivo txt en una matriz de caracteres, pero quiero que también me retorne en una variable diferente el número de líneas. Ahora otra pregunta, ¿se puede declarar una función dentro de una función? es decir, funciones anidadas.

Gracias de antemano.

Salvador Pozo
2012-05-23 14:37:54

Respondo a tus preguntas, Diego.

No, una función C++ sólo puede devolver un valor. Sin embargo, cuando veamos las estructuras, en el capítulo 11, verás que ese valor puede ser una estructura, y por lo tanto, contener varios valores. Otra opción es usar parámetros por referencia o que sean punteros. Los cambios hechos en los valores referenciados se conservan al regresar la función. Veremos punteros en el capítulo 12 y referencias en el 15.

Sí, se puede declarar una función dentro de otra. Sin embargo no se pueden definir funciones dentro de funciones en C++. Declarar y definir funciones son cosas diferentes.

En C sí es posible, el inconveniente (o ventaja) es que se tratará de una función local, es decir, sólo podrá ser invocada desde la función en que fue declarada y definida, y será inaccesible para el resto de las funciones.

Hasta pronto

Marcelo
2012-08-21 03:39:09

Recien me estoy iniciando y hago cosas sencillas aunque trato de usar todo lo que voy aprendiendo. ¿Que estoy haciendo mal en el siguiente código?

#include <vcl.h>

#pragma hdrstop

#include <iostream.h>

#include <conio.h>

#pragma argsused

float calcular (int a , int b);

int main(int argc, char* argv[])

{

float total;

total = calcular (int a , int b);

cout << "El resultado de su operacion es: " << total;

system ("pause");

return 0;

}

float calcular (int a , int b)

{

int opc;

cout << "¿Que operacion desea realizar?\n 1 = Suma; 2 = Resta; 3 = Multiplicar; 4 = Dividir: ";

cin >> opc;

cout << "Ingrese el primer valor: "; cin >> a;

cout << "\nIngrese el segundo valor: "; cin >> b;

switch (opc) {

case 1:

return a + b;

break;

case 2:

return a - b;

break;

case 3:

return a * b;

break;

case 4:

if (!b) cout << "No se puede dividir por 0.";

else return a / b;

}

}

Jose
2012-09-01 15:40:37

Saludos

En primer lugar fellicitarlos por este valioso esfuerzo.

En segundo lugar, pedirles su ayuda, estoy iniciando en esto de la programación y me han asignado escribir un código usando funciones, estoy claro en el caso de que primero debo declarar la función, luego definirla y por último llamar la función; el programa a crear debe simplificar una fracción al ingresar el usuario el numerador y denominador, lo que necesito es una idea de cómo difinir la función.

Agradezco su ayuda.

Gibson Hernandez
2012-09-10 04:24:04

mmmm bueno pienso que todo esto es muy bueno pero yo estoy en II de bachillerato y estoy en este tema de funciones y no entiendo muy bien y quisiera que me ayudaras de una forma de como entenderlo mejor por que mi profesor solo me lo enseño una vez y me puso a hacer programas sin entenderle asi que si me podes ayudar!!!! te lo voy a agradecer :)

Jeannette
2012-09-16 06:52:38

Hola, hace unas semanas empece a ver funciones en c++, y queria pedirle ayuda con algunos ejemplos para que pueda compreder mejor, agradeceria mucho.

Bendiciones!!!

angel
2012-09-18 23:56:48

Hola quisiera saber si hace falta cambiar el ámbito de una variable para sacarla de una función o la puedo sacar directamente con return.

La variable se declara y se asigna dentro de la función.

Anónimo
2012-09-25 03:59:52

gracias por su ayuda

Pablo
2012-09-26 03:15:59

Hola, antes que nada muchisimas gracias por el excelente curso. Queria hacerte una pregunta, por comodidad y cuidar la vista, preferiria leer el libro imprimible antes que leer desde la pc, pero el tema es que fue hecho en el 2003, ya casi 10 años atras, por lo que asumo que podria haber correccions como asi tambien nuevos ejemplos y demas, queria saber si usted hara una nueva version en PDF o si considera que la del 2003 esta mas que bien para imprimir. Desde ya muchisimas gracias.

ROLLY
2012-10-19 02:37:58

SABES AUN NO ENTIENDO QUE ES UNA FUNCION, UN PUNTERO, ARREGLOS....... NO SE QUE LIBRO ME RECOMIENDAN?

jadr
2012-10-21 20:08:23

Para mantener la coherencia con la sintaxis acordada creo que la definición de una función debería modificarse a:

[extern|static] <tipo_valor_retorno> [<modificadores>] <identificador>(<lista_parámetros>)
{
   [<sentencias>]
}

A.- "modificadores" y "sentencias" deben ir entre signos "<>" ya que deben ser sustituidos por el texto adecuado que realice el trabajo nombrado.

B.- "extern" debe mantenerse subrayado. No he podido escribirlo de otra manera al utilizar el formulario de la pñagina web.

rolly mamani
2012-10-28 01:12:24

cula es mas importante, codificacion o diagrama de flujo...

betty nancy
2012-12-11 17:31:43

para realizar el llamado de las funciones de forma externa (lenguaje c++) es decir sin que este dentro del codigo fuente como debo proceder?. Por favor un pequeño ejemplo

B. Amauri
2013-01-09 02:22:49

¡Hola! Tengo el siguiente código, por cierto es parte de la solución a uno de sus ejercicios, pero el compilador dice que me falta un ; antes de la llave que abre mi función "Ordenar", lo cual significa que no está reconociendo la definición de esta. ¿Qué puede ser?

#include <iostream>
using namespace std;

int array_1[10],i,round;
char tipo_orden;
 
//La siguiente función ordena la cadena

int Ordenar(tipo_orden)
{
	int cambio=0;

	//Cuando el ordenamiento sea ascendente
	if(tipo_orden=='a')
	{
		round=0;
		do
		{
			//Se revisan los elementos del array y se ordenan por pares
			for(i=1;array_1[i];i++)
			{
				if(array_1[i]<array_1[i-1]) {cambio=array_1[i]; array_1[i]=array_1[i-1]; array_1[i-1]=cambio;}
			}
	
			round++
		}
		while(array_1[round]); //El ciclo se repite mientras exista el elemento array_1[round], round es la pasada por el array
	}

	//Cuando el ordenamiento sea descendente
	else if(tipo_orden=='z')
	{
		round=0;
		do
		{
			//Se revisan los elementos del array y se ordenan por pares
			for(i=1;array_1[i];i++)
			{
				if(array_1[i]>array_1[i-1]) {cambio=array_1[i]; array_1[i]=array_1[i-1]; array_1[i-1]=cambio;}
			}
	
			round++;
		}
		while(array_1[round]); //El ciclo se repite mientras exista el elemento array_1[round], round es la pasada por el array
	}
	
	return 0;
}

int main()
...

De hecho la función era void, pero también decía: Error: se declara el campo Ordenar como void.

wil
2013-03-06 13:34:34

hola muchas gracias por el tutorial

estube realizando un programa pero no devuelve nada como resultado

mi idea es mostrar por pantalla la suma de dos numeros

#include <iostream.h>

void sumar(int ,int);

int main(){

int a,b;

a=1;

b=2;

sumar(a,b);

return 0;

}

void sumar(int a, int b){

cout << a+b;

}

LuisAngel
2013-03-15 15:48:19

Hola Will... respondo a tu pregunta, tu programa no retorna ninguna valor porque usaste void; es decir que no retorne nada, en lugar de void debe ir en este caso int..

quedando asi:

int sumar(int a,int b)

{

int suma=0;

suma=a+b; return suma;

}

Phato
2013-05-29 07:58:18

Hola will aparte de la correccion de tu codigo que ya te mencionaron debes recordar que debes asignar el valor de retorno a una variable para que puedas usar ese resultado como una variable mas de tu programa, caso contrario solo mandala a imprimir ya sea con cout o con printf saludos cordiales

jhon
2013-09-04 07:39:34

Hay todavía no logro entender mucho sobre funciones!!! voy a seguir leyendo para ver si me encaja todo ya que leo y me confundo demasiado y después no se para que sirve eso o tal etc..

Steven R. Davidson
2013-09-04 17:39:27

Hola Jhon,

Es normal que no entiendas todo acerca de las funciones al terminar este capítulo. Esto es porque las funciones sirven a modo de pequeños programas. De hecho, en la informática se usan otros términos que son sinónimos de "funciones", como: rutinas, subrutinas, procedimientos, subprogramas, módulos, métodos, y unos cuantos más. Como todavía no hemos visto la forma de programar, obviamente no podemos decir mucho más acerca de las funciones por el momento.

Tendrás mayor claridad sobre el asunto cuando termines de leer el capítulo 6. Además, recomiendo que mires los ejemplos completos al final del capítulo 6 para entender mejor todos los temas de los primeros capítulos.

Espero que esto aclare la inquietud.

Steven

luis angel espinoza
2013-11-15 01:42:49

quisiera saber como hago una lista de n numero de nombres, con dirección, telefofo,etc.

pero en el cual utilice clases con funciones y estructuras con arreglos todo en un solo programa podrían ayudarme

ana
2014-03-27 01:49:17

hola!les agradeceria mucho si me pudieran ayudar con este problema, recien estoy aprendiendo y no se que me quiere decir con parametros.

crear una funcion llamada cuadrado que calcule el area de un cuadrado. la funacion debe recibir como parametros el lado del cuadrado. luego escriba un programa para utilizar dicha funcion.