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)
{
}
Entrambi funzionano; qual è il modo standard e perché ?
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)
{
}
Entrambi funzionano; qual è il modo standard e perché ?
Risposte:
Se inserisci la dichiarazione in un file di intestazione e la definizione in un .cpp
file separato e #include
l'intestazione di un .cpp
file diverso , sarai in grado di vedere la differenza.
In particolare, supponiamo:
int Add(int a, int b);
int Add(int a, int b = 3) {
...
}
#include "lib.h"
int main() {
Add(4);
}
La compilazione di test.cpp
non vedrà la dichiarazione del parametro predefinito e non riuscirà con un errore.
Per questo motivo, la definizione del parametro predefinito è generalmente specificata nella dichiarazione della funzione :
int Add(int a, int b = 3);
b
viene definito una volta per ogni .cpp
file che include l'intestazione. Ma va bene, perché hai una sola dichiarazione della Add
funzione.
In C ++ i requisiti imposti agli argomenti predefiniti per quanto riguarda la loro posizione nell'elenco dei parametri sono i seguenti:
L'argomento predefinito per un determinato parametro non deve essere specificato più di una volta. Specificarlo più di una volta (anche con lo stesso valore predefinito) è illegale.
I parametri con argomenti predefiniti devono formare un gruppo contiguo alla fine dell'elenco dei parametri.
Ora, tenendo presente ciò, in C ++ è possibile "far crescere" l'insieme di parametri che hanno argomenti predefiniti da una dichiarazione della funzione alla successiva, purché i requisiti di cui sopra siano costantemente soddisfatti.
Ad esempio, è possibile dichiarare una funzione senza argomenti predefiniti
void foo(int a, int b);
Per chiamare quella funzione dopo tale dichiarazione dovrai specificare esplicitamente entrambi gli argomenti.
Più tardi (più in basso) nella stessa unità di traduzione, è possibile dichiararlo nuovamente, ma questa volta con un argomento predefinito
void foo(int a, int b = 5);
e da questo punto in poi puoi chiamarlo con un solo argomento esplicito.
Più in basso è possibile dichiararlo nuovamente aggiungendo un altro argomento predefinito
void foo(int a = 1, int b);
e da questo punto in poi puoi chiamarlo senza argomenti espliciti.
L'esempio completo potrebbe apparire come segue
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)
{
// ...
}
Per quanto riguarda il codice nella tua domanda, entrambe le varianti sono perfettamente valide, ma significano cose diverse. La prima variante dichiara subito un argomento predefinito per il secondo parametro. La seconda variante inizialmente dichiara la tua funzione senza argomenti predefiniti, quindi ne aggiunge una per il secondo parametro.
L'effetto netto di entrambe le dichiarazioni (ovvero il modo in cui viene visto dal codice che segue la seconda dichiarazione) è esattamente lo stesso: la funzione ha argomento predefinito per il suo secondo parametro. Tuttavia, se riesci a spremere del codice tra la prima e la seconda dichiarazione, queste due varianti si comporteranno diversamente. Nella seconda variante la funzione non ha argomenti predefiniti tra le dichiarazioni, quindi dovrai specificare entrambi gli argomenti in modo esplicito.
void foo(int a = 1, int b)
funzionare, deve essere dichiarato dopo void foo(int a, int b = 5)
. Sì, funzionerà. E no, non è un errore di sintassi. g ++ 4.5.3 lo compilerà perfettamente.
int foo(int)
. Trovo di poter scrivere di int foo(int=5)
nuovo, tralasciando i nomi dei parametri. Nessuno sembra averlo ancora menzionato.
Il primo modo sarebbe preferito al secondo.
Questo perché il file di intestazione mostrerà che il parametro è facoltativo e quale sarà il suo valore predefinito. Inoltre, ciò garantirà che il valore predefinito sia lo stesso, indipendentemente dall'implementazione del file .cpp corrispondente.
Nel secondo modo, non vi è alcuna garanzia di un valore predefinito per il secondo parametro. Il valore predefinito potrebbe cambiare, in base alla modalità di implementazione del file .cpp corrispondente.
Gli argomenti predefiniti devono essere specificati con la prima occorrenza del nome della funzione, in genere nel prototipo della funzione. Se il prototipo della funzione viene omesso perché la definizione della funzione funge anche da prototipo, è necessario specificare gli argomenti predefiniti nell'intestazione della funzione.
b
verrà definito più volte, una volta per ogni unità di compilazione che includelib.h
, giusto?