Valor predeterminado del parámetro de función


1.

int Add (int a, int b = 3);
int Add (int a, int b)
{

}

2.

int Add (int a, int b);
int Add (int a, int b = 3)
{

}

Ambos funcionan; ¿cuál es el camino estándar y por qué?

Author: River, 2010-05-16

4 answers

Si coloca la declaración en un archivo de encabezado, y la definición en un archivo .cpp separado, y #include el encabezado de un archivo .cpp diferente, podrá ver la diferencia.

Específicamente, supongamos:

[12] Lib.h
int Add(int a, int b);
[12] Lib.cpp
int Add(int a, int b = 3) {
   ...
}

Prueba.cpp

#include "lib.h"

int main() {
    Add(4);
}

La compilación de test.cpp no verá la declaración de parámetros por defecto, y fallará con un error.

Por esta razón, la definición de parámetro por defecto generalmente se especifica en la función declaración:

[12] Lib.h
int Add(int a, int b = 3);
 173
Author: Greg Hewgill,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-05-16 07:56:47

En C++ los requisitos impuestos a los argumentos predeterminados con respecto a su ubicación en la lista de parámetros son los siguientes:

  1. El argumento predeterminado para un parámetro dado no se debe especificar más de una vez. Especificarlo más de una vez (incluso con el mismo valor predeterminado) es ilegal.

  2. Los parámetros con argumentos predeterminados deben formar un grupo contiguo al final de la lista de parámetros.

Ahora, teniendo esto en cuenta, en C++ se le permite "grow" el conjunto de parámetros que tienen argumentos predeterminados de una declaración de la función a la siguiente, siempre y cuando los requisitos anteriores se cumplan continuamente.

Por ejemplo, puede declarar una función sin argumentos predeterminados

void foo(int a, int b);

Para llamar a esa función después de dicha declaración, tendrá que especificar ambos argumentos explícitamente.

Más adelante (más abajo) en la misma unidad de traducción, puede volver a declararlo, pero esta vez con un valor predeterminado argumento

void foo(int a, int b = 5);

Y a partir de este punto se puede llamar con un solo argumento explícito.

Más abajo se puede volver a declarar una vez más añadiendo un argumento predeterminado más

void foo(int a = 1, int b);

Y a partir de este punto se puede llamar sin argumentos explícitos.

El ejemplo completo podría verse como sigue

void foo(int a, int b);

int main()
{
  foo(2, 3);

  void foo(int a, int b = 5); // redeclare
  foo(8); // OK, calls `foo(8, 5)`

  void foo(int a = 1, int b); // redeclare again
  foo(); // OK, calls `foo(1, 5)`
}

void foo(int a, int b)
{
  // ...
}

En cuanto al código en tu pregunta, ambas variantes son perfectamente válidas, pero significan cosas diferentes. La primera variante declara un argumento por defecto para el segundo parámetro de inmediato. La segunda variante declara inicialmente su función sin argumentos predeterminados y luego agrega uno para el segundo parámetro.

El efecto neto de ambas declaraciones (es decir, la forma en que se ve por el código que sigue a la segunda declaración) es exactamente el mismo: la función tiene un argumento predeterminado para su segundo parámetro. Sin embargo, si logra exprimir algo de código entre la primera y la segunda declaración, estas dos variantes se comportarán de manera diferente. En la segunda variante la función no tiene argumentos predeterminados entre las declaraciones, por lo que tendrá que especificar ambos argumentos explícitamente.

 40
Author: AnT,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-08-03 17:25:14

Los argumentos predeterminados deben especificarse con la primera aparición del nombre de la función, normalmente en el prototipo de función. Si el prototipo de función se omite porque la definición de función también sirve como prototipo, entonces los argumentos predeterminados deben especificarse en el encabezado de la función.

 4
Author: clyfe,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-05-16 07:40:09

La primera vía sería preferible a la segunda.

Esto se debe a que el archivo de encabezado mostrará que el parámetro es opcional y cuál será su valor predeterminado. Además, esto asegurará que el valor predeterminado sea el mismo, sin importar la implementación del correspondiente .archivo cpp.

De la segunda manera, no hay garantía de un valor predeterminado para el segundo parámetro. El valor predeterminado podría cambiar, dependiendo de cómo el correspondiente .archivo cpp es aplicado.

 3
Author: user342264,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-05-16 07:43:42