Dove mettere il valore del parametro predefinito in C ++?

Qual è il posto per il valore del parametro predefinito? Solo nella definizione della funzione, o dichiarazione, o in entrambi i posti?

I valori dei parametri di default devono apparire nella dichiarazione, poiché questa è l’unica cosa che vede il chiamante.

EDIT: Come altri sottolineano, puoi avere l’argomento sulla definizione, ma ti consiglio di scrivere tutto il codice come se non fosse vero.

Puoi fare entrambi, ma mai entrambi. Di solito lo fai alla dichiarazione di funzione e quindi tutti i chiamanti possono usare quel valore predefinito. Tuttavia puoi farlo alla definizione della funzione e poi solo quelli che vedono la definizione saranno in grado di utilizzare il valore predefinito.

Il posto più utile è nella dichiarazione (.h) in modo che tutti gli utenti lo vedano.

Ad alcune persone piace aggiungere anche i valori predefiniti nell’implementazione (come commento):

void foo(int x = 42, int y = 21); void foo(int x /* = 42 */, int y /* = 21 */) { ... } 

Tuttavia, questo significa duplicazione e aggiungerà la possibilità di avere il commento fuori sincrono con il codice (cosa c’è di peggio di codice non commentato? Codice con commenti fuorvianti!).

Anche se questo è un thread “vecchio”, vorrei comunque aggiungere quanto segue:

Ho sperimentato il prossimo caso:

  • Nel file di intestazione di una class, ho avuto
 int SetI2cSlaveAddress( UCHAR addr, bool force ); 
  • Nel file sorgente di quella class, l’ho avuto
 int CI2cHal::SetI2cSlaveAddress( UCHAR addr, bool force = false ) { ... } 

Come si può vedere, ho inserito il valore predefinito del parametro “force” nel file sorgente della class, non nel file di intestazione della class.

Quindi ho usato quella funzione in una class derivata come segue (la class derivata ha ereditato la class base in modo pubblico):

SetI2cSlaveAddress( addr );

supponendo che prenderebbe il parametro “force” come “false” “per assegnato”.

Tuttavia, il compilatore ( messo in modalità c ++ 11 ) si è lamentato e mi ha dato il seguente errore del compilatore:

 /home/.../mystuff/domoproject/lib/i2cdevs/max6956io.cpp: In member function 'void CMax6956Io::Init(unsigned char, unsigned char, unsigned int)': /home/.../mystuff/domoproject/lib/i2cdevs/max6956io.cpp:26:30: error: no matching function for call to 'CMax6956Io::SetI2cSlaveAddress(unsigned char&)' /home/.../mystuff/domoproject/lib/i2cdevs/max6956io.cpp:26:30: note: candidate is: In file included from /home/geertvc/mystuff/domoproject/lib/i2cdevs/../../include/i2cdevs/max6956io.h:35:0, from /home/geertvc/mystuff/domoproject/lib/i2cdevs/max6956io.cpp:1: /home/.../mystuff/domoproject/lib/i2cdevs/../../include/i2chal/i2chal.h:65:9: note: int CI2cHal::SetI2cSlaveAddress(unsigned char, bool) /home/.../mystuff/domoproject/lib/i2cdevs/../../include/i2chal/i2chal.h:65:9: note: candidate expects 2 arguments, 1 provided make[2]: *** [lib/i2cdevs/CMakeFiles/i2cdevs.dir/max6956io.cpp.o] Error 1 make[1]: *** [lib/i2cdevs/CMakeFiles/i2cdevs.dir/all] Error 2 make: *** [all] Error 2 

Ma quando ho aggiunto il parametro predefinito nel file di intestazione della class base:

int SetI2cSlaveAddress( UCHAR addr, bool force = false );

e rimosso dal file sorgente della class base:

int CI2cHal::SetI2cSlaveAddress( UCHAR addr, bool force )

quindi il compilatore era felice e tutto il codice funzionava come previsto (potrei dare uno o due parametri alla funzione SetI2cSlaveAddress() )!

Quindi, non solo per l’utente di una class, è importante inserire il valore predefinito di un parametro nel file di intestazione, anche la sua compilazione e la sua funzionalità sembrano apparentemente indispensabili!

Se le funzioni sono esposte – non membri, pubbliche o protette – allora il chiamante dovrebbe conoscerle e i valori predefiniti devono essere nell’intestazione.

Se le funzioni sono private e out-of-line, allora ha senso inserire i valori predefiniti nel file di implementazione perché ciò consente modifiche che non triggersno la ricompilazione del client (un problema a volte serio per le librerie di basso livello condivise in scala aziendale sviluppo). Detto questo, è sicuramente potenzialmente confuso, e c’è un valore di documentazione nel presentare l’API in un modo più intuitivo nell’intestazione, quindi scegli il tuo compromesso, anche se la coerenza è la cosa principale quando non ci sono motivi validi in ogni caso.

la dichiarazione è generalmente la più “utile”, ma dipende da come si desidera utilizzare la class.

entrambi non sono validi

Buona domanda … Trovo che i programmatori usino tipicamente la dichiarazione per dichiarare i valori predefiniti. Sono stato tenuto in un modo (o avvertito) o l’altro anche in base al compilatore

 void testFunct(int nVal1, int nVal2=500); void testFunct(int nVal1, int nVal2) { using namespace std; cout << nVal1 << << nVal2 << endl; } 

Un altro punto non ho trovato nessuno menzionato:

Se hai un metodo virtuale, ogni dichiarazione può avere il suo valore predefinito!

Dipende dall’interfaccia che stai chiamando quale valore verrà utilizzato.

Esempio su ideone

 struct iface { virtual void test(int a = 0) { std::cout << a; } }; struct impl : public iface { virtual void test(int a = 5) override { std::cout << a; } }; int main() { impl d; d.test(); iface* a = &d; a->test(); } 

Stampa 50

Vi scoraggio vivamente di usarlo in questo modo

Si può fare in entrambi (secondo lo standard), ma ricorda, se il tuo codice vede la dichiarazione senza argomenti predefiniti prima della definizione che contiene l’argomento predefinito, allora l’errore di compilazione può arrivare.

Ad esempio, se si include un’intestazione contenente una dichiarazione di funzione senza elenco di argomenti predefinito, il compilatore cercherà il prototipo in quanto non conosce i valori di argomento predefiniti e quindi il prototipo non corrisponderà.

Se stai mettendo la funzione con argomento predefinito nella definizione, allora includi quel file ma non lo suggerirò.

Aggiungere un altro punto. Le dichiarazioni delle funzioni con argomento predefinito devono essere ordinate da destra a sinistra e dall’alto verso il basso .

Ad esempio, nella dichiarazione della funzione sottostante se si modifica l’ordine di dichiarazione, il compilatore fornisce un errore di parametro predefinito mancante. Il compilatore consente di separare la dichiarazione della funzione con l’argomento predefinito all’interno dello stesso ambito, ma dovrebbe essere in ordine da DESTRA a SINISTRA (argomenti predefiniti) e da TOP a BOTTOM (argomento predefinito dichiarazione ordine di funzione).

 //declaration void function(char const *msg, bool three, bool two, bool one = false); void function(char const *msg, bool three = true, bool two, bool one); // Error void function(char const *msg, bool three, bool two = true, bool one); // OK //void function(char const *msg, bool three = true, bool two, bool one); // OK int main() { function("Using only one Default Argument", false, true); function("Using Two Default Arguments", false); function("Using Three Default Arguments"); return 0; } //definition void function(char const *msg, bool three, bool two, bool one ) { std::cout<