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 trabajan; ¿Cuál es la forma estándar y por qué ?
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 trabajan; ¿Cuál es la forma estándar y por qué ?
Respuestas:
Si coloca la declaración en un archivo de encabezado, y la definición en un .cpp
archivo separado , y #include
el encabezado de un .cpp
archivo diferente , podrá ver la diferencia.
Específicamente, suponga:
int Add(int a, int b);
int Add(int a, int b = 3) {
...
}
#include "lib.h"
int main() {
Add(4);
}
La compilación de test.cpp
no verá la declaración de parámetro predeterminada y fallará con un error.
Por esta razón, la definición de parámetro predeterminada generalmente se especifica en la declaración de función :
int Add(int a, int b = 3);
b
se define una vez para cada .cpp
archivo que incluye el encabezado. Pero está bien, porque solo tienes una declaración de la Add
función.
En C ++, los requisitos impuestos a los argumentos predeterminados con respecto a su ubicación en la lista de parámetros son los siguientes:
El argumento predeterminado para un parámetro dado debe especificarse no más de una vez. Es ilegal especificarlo más de una vez (incluso con el mismo valor predeterminado).
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 "hacer crecer" el conjunto de parámetros que tienen argumentos predeterminados de una declaración de la función a la siguiente, siempre que los requisitos anteriores se satisfagan 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, deberá especificar ambos argumentos explícitamente.
Más adelante (más abajo) en la misma unidad de traducción, puede volver a declararlo nuevamente, pero esta vez con un argumento predeterminado
void foo(int a, int b = 5);
y a partir de este momento puedes llamarlo con un solo argumento explícito.
Más abajo, puede volver a declararlo una vez más agregando un argumento predeterminado más
void foo(int a = 1, int b);
y a partir de este momento puedes llamarlo sin argumentos explícitos.
El ejemplo completo podría verse de la siguiente manera
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 su pregunta, ambas variantes son perfectamente válidas, pero significan cosas diferentes. La primera variante declara un argumento predeterminado 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 lo ve 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 logras 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 deberá especificar ambos argumentos explícitamente.
void foo(int a = 1, int b)
que funcione, debe declararse después void foo(int a, int b = 5)
. Sí, funcionará Y no, no es un error de sintaxis. g ++ 4.5.3 lo compilará perfectamente bien.
int foo(int)
. Me parece que puedo int foo(int=5)
volver a escribir , dejando de lado los nombres de los parámetros. Nadie parece haber mencionado eso todavía.
La primera forma 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 garantizará que el valor predeterminado sea el mismo, sin importar la implementación del archivo .cpp correspondiente.
En la segunda forma, no hay garantía de un valor predeterminado para el segundo parámetro. El valor predeterminado podría cambiar, dependiendo de cómo se implemente el archivo .cpp correspondiente.
Los argumentos predeterminados deben especificarse con la primera aparición del nombre de la función, generalmente, en el prototipo de la función. Si se omite el prototipo de la función porque la definición de la función también sirve como prototipo, entonces los argumentos predeterminados deben especificarse en el encabezado de la función.
b
se definirá varias veces, una vez por cada unidad de compilación que incluyalib.h
, ¿es así?