2010-05-16 13 views

Respuesta

153

Si pones la declaración en un archivo de cabecera, y la definición en un archivo separado .cpp y #include el encabezado de un archivo diferente .cpp, usted será capaz de ver la diferencia.

En concreto, supongamos:

lib.h

int Add(int a, int b); 

lib.cpp

int Add(int a, int b = 3) { 
    ... 
} 

test.cpp

#include "lib.h" 

int main() { 
    Add(4); 
} 

La compilación de test.cpp no verá la defa declaración de parámetro ult, y fallará con un error.

Por esta razón, la definición de parámetros por defecto suele especificarse en la función declaración:

lib.h

int Add(int a, int b = 3); 
+0

Entonces 'b' se definirá varias veces, una para cada unidad de compilación que incluya' lib.h', ¿correcto? – httpinterpret

+0

@httpinterpret: en un sentido sí, el valor predeterminado de 'b' se define una vez para * cada *' archivo .cpp' que incluye el encabezado. Pero está bien, porque solo tiene una declaración de la función 'Agregar'. –

+0

@httpinterpret El compilador agregará el parámetro no especificado por el parámetro predeterminado cuando se genere el código de la persona que llama. Es por eso que el valor predeterminado DEBE estar en el prototipo de la función y no en la implementación de la función. El parámetro no está _definido_ en el sentido de definición de variable ya que el prototipo no define variables. – harper

4

argumentos por defecto debe ser especificado con la primera aparición del nombre-función típicamente, 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.

3

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 asegurará que el valor predeterminado sea el mismo, sin importar la implementación del archivo .cpp correspondiente.

En 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 se implemente el archivo .cpp correspondiente.

36

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

  1. argumento predeterminado para un parámetro dado tiene que ser especificado no 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, manteniendo esto en mente, en C++ que se les permite "crecer" 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 están continuamente satisfechos .

Por ejemplo, se puede declarar una función sin argumentos por defecto

void foo(int a, int b); 

Con el fin de llamar a esa función después de tal declaración se tendrá que especificar explícitamente los dos argumentos.

tarde (más abajo) en la misma unidad de traducción, puede volver a declarar de nuevo, pero esta vez con el argumento que viene por defecto

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

y desde este punto en adelante se le puede llamar con sólo una explícita argumento.

Más abajo se puede volver a declarar una vez más la adición de un argumento más por defecto

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

y desde este punto en adelante se le puede llamar sin argumentos explícitos.

El ejemplo completo podría tener el siguiente

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 una 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 apretar algún 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.

+0

No creo que tu código definido void foo (int a = 1, int b) funcionaría. Necesita tener todos los parámetros opcionales después de un parámetro opcional. Es un error de sintaxis (al menos con g ++ 4.5.3 en mi sistema). – Nilesh

+0

@Nilesh: Como dije explícitamente arriba (y cuál es el objetivo de este ejemplo) para 'void foo (int a = 1, int b)' trabajar, tiene que ser declarado * después de '' void foo (int a , int b = 5) '. Sí, funcionará. Y no, no es un error de sintaxis. g ++ 4.5.3 compilará perfectamente bien. – AnT

+0

De acuerdo, la función toma el valor de b de la declaración anterior. Obteniendo la cosa ahora. Gracias :-) – Nilesh

Cuestiones relacionadas