En programación informática , un argumento predeterminado es un argumento de una función que no se requiere que un programador especifique. En la mayoría de los lenguajes de programación, las funciones pueden tomar uno o más argumentos. Por lo general, cada argumento debe especificarse en su totalidad (este es el caso en el lenguaje de programación C [1] ). Los lenguajes posteriores (por ejemplo, en C++ ) permiten al programador especificar argumentos predeterminados que siempre tienen un valor, incluso si no se especifica uno al llamar a la función.
Argumentos predeterminados en C++
Considere la siguiente declaración de función:
int MiFunción ( int a , int b , int c = 12 );
Esta función toma tres argumentos, de los cuales el último tiene un valor predeterminado de doce. El programador puede llamar a esta función de dos maneras:
int resultado = MyFunc ( 1 , 2 , 3 ); resultado = MyFunc ( 1 , 2 );
En el primer caso, el valor del argumento llamado c se especifica explícitamente. En el segundo caso, se omite el argumento y se utiliza en su lugar el valor predeterminado de 12. En el caso de la función llamada, no hay forma de saber si el argumento ha sido especificado por el autor de la llamada o si se ha utilizado el valor predeterminado.
El método mencionado anteriormente es especialmente útil cuando se desea establecer criterios predeterminados para que la función pueda ser invocada con o sin parámetros. Considere lo siguiente:
void PrintGreeting ( std :: ostream & stream = std :: cout ) { // Esto envía un mensaje a la secuencia indicada. stream << "¡Hola mundo!" ; }
La llamada de función:
ImprimirSaludo ();
Por defecto, imprimirá " hola mundo !" en la salida estándar std::cout (normalmente la pantalla). Por otro lado, std::ostreamahora se puede pasar cualquier objeto de tipo a la misma función y la función imprimirá en el flujo dado en lugar de en la salida estándar. El ejemplo siguiente establece el valor std::ostream&en std::cerry, por lo tanto, imprime la salida en el flujo de error estándar.
ImprimirSaludo ( std :: cerr );
Dado que los valores de los argumentos predeterminados se "completan" en el sitio de la llamada en lugar de en el cuerpo de la función que se llama, las funciones virtuales toman sus valores de argumentos predeterminados del tipo estático del puntero o referencia a través del cual se realiza la llamada, en lugar de del tipo dinámico del objeto que suministra el cuerpo de la función virtual.
estructura Base { virtual std :: pair < int , int > Foo ( int x = 1 ) { return { x , 1 }; } };
struct Derivado : público Base { std :: pair < int , int > Foo ( int x = 2 ) anular { devolver { x , 2 }; } };
int main () { Derivado d ; Base & b = d ; assert ( d . Foo () == std :: make_pair ( 2 , 2 )); assert ( b . Foo () == std :: make_pair ( 1 , 2 )); }
Métodos sobrecargados
Algunos lenguajes, como Java , no tienen argumentos predeterminados. Sin embargo, se puede simular el mismo comportamiento utilizando la sobrecarga de métodos para crear métodos sobrecargados con el mismo nombre, que toman diferentes cantidades de argumentos; y las versiones con menos argumentos simplemente llaman a las versiones con más argumentos, con los argumentos predeterminados como los argumentos faltantes:
int MyFunc ( int a , int b ) { return MyFunc ( a , b , 12 ); } int MyFunc ( int a , int b , int c ) { /* implementación principal aquí */ }
Sin embargo, además de varias otras desventajas, dado que los argumentos predeterminados no se modelan en el sistema de tipos, el tipo de una devolución de llamada (también conocida como función de orden superior) no puede expresar que acepta ninguna de las sobrecargas ni simular los argumentos predeterminados con funciones sobrecargadas. Mientras que, en JavaScript, la definición de función no sobrecargada puede sustituir el valor predeterminado cuando el valor de entrada es undefined(independientemente de si fue implícitamente undefineda través de la ausencia del argumento en el sitio de llamada o un undefinedvalor pasado explícitamente); que se modela como un tipo de parámetro de argumento opcional ?:en TypeScript. La solución de JavaScript no se resuelve estáticamente (es decir, no en tiempo de compilación, por lo que TypeScript modela solo la opcionalidad y no los valores predeterminados en la firma de tipo de la función), por lo que incurre en una sobrecarga de tiempo de ejecución adicional, aunque proporciona más flexibilidad en el sentido de que las devoluciones de llamada pueden controlar independientemente sus valores predeterminados en lugar de estar dictados centralmente por la (firma de tipo de la devolución de llamada en la) firma de tipo de la función que ingresa la devolución de llamada. La solución TypeScript se puede simular en Java con el Optionaltipo excepto que el análogo de un implícito undefinedpara cada argumento ausente es un explícito Optional.<Integer>absent()en el sitio de la llamada.
Evaluación
Para cada llamada de función, se deben pasar valores de argumento predeterminados a la función llamada. Si un valor de argumento predeterminado contiene efectos secundarios, es importante saber cuándo se evalúan esos efectos secundarios: una vez para todo el programa (en el momento del análisis, la compilación o la carga) o una vez por llamada de función, en el momento de la llamada.
Python es un lenguaje notable que evalúa expresiones en argumentos predeterminados una sola vez, en el momento en que se evalúa la declaración de la función. Si se desea la evaluación por llamada de función, se puede replicar haciendo que el argumento predeterminado sea un valor centinela , como None, y luego haciendo que el cuerpo de la función evalúe los efectos secundarios del valor predeterminado solo si se pasó el valor centinela.
Por ejemplo:
importar aleatorio
def anxious ( a = random . random ()):
devuelve un
x = ansioso ()
y = ansioso ()
afirmar x == y
def lazy ( a = None ) :
si a es None :
a = random.random ( ) devuelve a
x = perezoso ()
y = perezoso ()
afirmar x != y
Medida
Generalmente, un argumento predeterminado se comportará de manera idéntica a un argumento pasado por parámetro o una variable local declarada al inicio de la función, y tendrá el mismo alcance y extensión (duración) que un parámetro u otra variable local, es decir, una variable automática que se desasigna al finalizar la función.
En otros casos, se puede asignar un argumento predeterminado de forma estática. Si la variable es mutable, conservará su valor en todas las llamadas de función, como sucede con una variable estática .
Este comportamiento se encuentra en Python para tipos mutables, como listas. Al igual que con la evaluación, para garantizar la misma extensión que una variable local, se puede utilizar un valor centinela:
def anxious ( a = []):
devuelve un
x = ansioso ()
x += [ 1 ]
afirmar ansioso () == [ 1 ]
def lazy ( a = None ):
si a es None :
a = []
devuelve a
x = perezoso ()
x += [ 1 ]
afirmar perezoso () == []
Referencias
- ^ Leslie, Martin. «Parámetros predeterminados». Referencia de programación en C++ . Archivado desde el original el 9 de octubre de 2011. Consultado el 13 de enero de 2012 .