2009-12-10 24 views
33

Non sono riuscito a trovare una risposta chiara a questo sebbene ciò potrebbe essere dovuto al fatto che non stavo utilizzando i termini di ricerca corretti, quindi per favore reindirizzami se è il caso. È possibile utilizzare gli argomenti precedenti in un elenco di parametri delle funzioni come valore predefinito per gli argomenti successivi nell'elenco dei parametri? Per esempio,C/C++ argomento predefinito impostato come argomento precedente

void f(int a, int b = a, int c = b); 

Se questo è possibile ci sono delle regole d'uso? Qualche differenza tra C e C++?

+6

Per rispondere a questa parte della tua domanda, non v'è alcuna ** ** nozione di argomento di default in C. –

risposta

52

La risposta è no, non si può. È possibile ottenere il comportamento desiderato utilizzando gli overload:

void f(int a, int b, int c); 
inline void f(int a, int b) { f(a,b,b); } 
inline void f(int a)  { f(a,a,a); } 

Come per l'ultima domanda, C non consente affatto i parametri di default.

+1

Perché hai inserito solo due delle funzioni? –

+5

@DavidDoria: Non abbiamo idea se il sovraccarico principale possa o debba essere inarcato - questo va oltre lo scopo della domanda. Gli altri chiamano semplicemente il sovraccarico principale, e quindi possono essere banali. –

25

No, non è legale C++. Questo è riportato alla sezione 8.3.6/9 della ++ standard C:

Default arguments are evaluated each time the function is called. The order of evaluation of function arguments is unspecified. Consequently, parameters of a function shall not be used in default argument expressions, even if they are not evaluated.

e:

int f(int a, int b = a); // error: parameter a used as default argument

E C89 almeno non supporta i valori di default dei parametri.

3

Questo non è possibile

2

No, non puoi farlo.
Riceverai sicuramente un errore "La variabile locale potrebbe non apparire in questo contesto".

7

Come un potenziale soluzione alternativa, si potrebbe fare:

const int defaultValue = -999; // or something similar 

void f(int a, int b = defaultValue, int c = defaultValue) 
{ 
    if (b == defaultValue) { b = a; } 
    if (c == defaultValue) { c = b; } 

    //... 
} 
+0

uno stava per scrivere questo pure –

+0

Grazie. Guardando le altre risposte, penso che l'approccio di Mike Seymour sia ancora migliore. –

+2

Questo risolverà il valore predefinito in fase di esecuzione. L'approccio di Mike è risolto al momento della compilazione. Inoltre, questo suppone che il tipo (qui int) possa avere uno speciale valore di flag "default" (qui -999), e quello che fai è pericoloso: se in qualche modo -999 viene passato come valore reale questo non funzionerà come previsto. .. – galinette

1

Non penso che si possa fare in quanto si tratta di una sintassi illegale. Tuttavia, consultare lo standard C99 in formato pdf (n1136.pdf).

Tuttavia, è possibile aggirare il problema utilizzando static come nel dichiarare le variabili statiche e li utilizzano all'interno della funzione f

 
static int global_a; 

/* In some other spot where you are calling f(), do this beforehand */ 
/* global_a = 4; f(); */ 

void f(void){ 
    int a = global_a; 
    b = c = a; 
    /* ..... */ 
} 

Complimenti a Michael Burr per sottolineare il mio errore! :)

Sembra che sia necessario rivedere il codice e modificarlo per qualcosa di simile.

Spero che questo aiuti, Cordiali saluti, Tom.

+0

Non seguo - se fai qualcosa di simile, non c'è motivo di passare i parametri perché non vengono usati. –

+0

@ Michael Burr: Sì, hai ragione ... mio male! Meh ... Lo modifico di conseguenza e cito il tuo contributo. Grazie! :) – t0mm13b

1

La tua prima idea potrebbe essere quella di fare qualcosa di simile:

void something(int a, int b=-1, int c=-1){ 
    if(b == -1) 
     b = a; 
    if(c == -1) 
     c = b; 
} 

Ho usato -1 perché questa funzione è disponibile solo con valori positivi. Ma cosa succede se qualcuno usa la mia classe e commette un errore che finisce per inviare -1 al metodo? Sarebbe ancora compilato ed eseguito, ma il risultato sarebbe imprevedibile per l'utente.Quindi la cosa intelligente da fare sarebbe quella di rimuovere ogni argomento di default e invece fare un sacco di metodi con lo stesso nome come questo:

void something(int a, int b, int c){ 
    /* Do something with a, b and c */ 
} 

void something(int a){ 
    something(a, a, a); 
} 

void something(int a, int b){ 
    something(a, b, b); 
} 

Essa in realtà non ci vuole molto più tempo per il codice, e se qualcuno lo usa in un'interfaccia di programmazione con funzionalità di completamento automatico, mostrerà i 3 possibili prototipi.

Problemi correlati