Cerca nel sito:
ricerca
avanzata

Frasi Celebri...

Picchieresti un uomo con gli occhiali? No, userei qualcosa di pi? pesante.

Marco Bini 

Sondaggio:

Windows XP ?...

Un grande affare
Il Sistema Operativo migliore sul mercato
Bello, ma niente di eccezionale
L'ennesima fregatura Microsoft
Una ciofeca peggiore dei suoi predecessori
Preferisco non commentare...

visualizza risultati


 

Passaggio di parametri e argomenti di default

I parametri di una funzione si comportano all'interno del corpo della funzione come delle variabili locali e possono quindi essere usati anche a sinistra di un assegnamento (per quanto riguarda le variabili locali ad una funzione, si rimanda al capitolo III, paragrafo 3):

 

void Assign(int a, int b) {
  a = b;         // Tutto OK, operazione lecita!
}

 

tuttavia qualsiasi modifica ai parametri formali (quelli cioe` che compaiono nella definizione, nel nostro caso a e b) non si riflette (per quanto visto fin'ora) automaticamente sui parametri attuali (quelli effettivamente usati in una chiamata della funzione):

 

#include < iostream >
using namespace std;

void Assign(int a, int b) {
  cout << "Inizio Assign, parametro a = " << a << endl;
  a = b;
  cout << "Fine Assign, parametro a = " << a << endl;
}

int main(int, char* []) {
  int X = 5;
  int Y = 10;

  cout << "X = " << X << endl;
  cout << "Y = " << Y << endl;

  // Chiamata della funzione Assign
  // con parametri attuali X e Y

  Assign(X, Y);

  cout << "X = " << X << endl;
  cout << "Y = " << Y << endl;
  return 0;
}

 

L'esempio appena visto e` perfettamente funzionante e se eseguito mostrerebbe come la funzione Assign, pur eseguendo una modifica ai suoi parametri formali, non modifichi i parametri attuali. Questo comportamento e` perfettamente corretto in quanto i parametri attuali vengono passati per valore: ad ogni chiamata della funzione viene cioe` creata una copia di ogni parametro localmente alla funzione stessa; tali copie vengono distrutte quando la chiamata della funzione termina ed il loro contenuto non viene copiato nelle eventuali variabili usate come parametri attuali.
In alcuni casi tuttavia puo` essere necessario fare in modo che la funzione possa modificare i suoi parametri attuali, in questo caso e` necessario passare non una copia, ma un riferimento o un puntatore e agire su questo per modificare una variabile non locale alla funzione. Per adesso non considereremo queste due possibilita`, ma rimanderemo la cosa al capitolo successivo non appena avremo parlato di puntatori e reference.

A volte siamo interessati a funzioni il cui comportamento e` pienamente definito anche quando in una chiamata non tutti i parametri sono specificati, vogliamo cioe` essere in grado di avere degli argomenti che assumano un valore di default se per essi non viene specificato alcun valore all'atto della chiamata. Ecco come fare:

 

int Sum (int a = 0, int b = 0) {
  return a+b;
}

 

Quella che abbiamo appena visto e` la definizione della funzione Sum ai cui argomenti sono stati associati dei valori di default (in questo caso 0 per entrambi gli argomenti), ora se la funzione Sum viene chiamata senza specificare il valore di a e/o b il compilatore genera una chiamata a Sum sostituendo il valore di default (0) al parametro non specificato. Una funzione puo` avere piu` argomenti di default, ma le regole del C++ impongono che tali argomenti siano specificati alla fine della lista dei parametri formali nella dichiarazione della funzione:

 

void Foo(int a, char b = 'a') {
  /* ... */
}           // Ok!

void Foo2(int a, int c = 4, float f) {
  /* ... */
}           // Errore!

void Foo3(int a, float f, int c = 4) {
  /* ... */
}           // Ok!

 

La dichiarazione di Foo2 e` errata poiche` quando viene specificato un argomento con valore di default, tutti gli argomenti seguenti (in questo caso f) devono possedere un valore di default; l'ultima definizione mostra come si sarebbe dovuto definire Foo2 per non ottenere errori.

La risoluzione di una chiamata di una funzione con argomenti di default naturalmente differisce da quella di una funzione senza argomenti di default in quanto sono necessari un numero di controlli maggiori; sostanzialmente se nella chiamata per ogni parametro formale viene specificato un parametro attuale, allora il valore di ogni parametro attuale viene copiato nel corrispondente parametro formale sovrascrivendo eventuali valori di default; se invece qualche parametro non viene specificato, quelli forniti specificano il valore dei parametri formali secondo la loro posizione e per i rimanenti parametri formali viene utilizzato il valore di default specificato (se nessun valore di default e` stato specificato, viene generato un errore):

 

// riferendo alle precedenti definizioni:

Foo(1, 'b');       // chiama Foo con argomenti 1 e 'b'
Foo(0);            // chiama Foo con argomenti 0 e 'a'
Foo('c');          // ?????
Foo3(0);           // Errore, mancano parametri!
Foo3(1, 0.0);      // chiama Foo3(1, 0.0, 4)
Foo3(1, 1.4, 5);   // chiama Foo3(1, 1.4, 5)

 

Degli esempi appena fatti, il quarto, Foo3(0), e` un errore poiche` non viene specificato il valore per il secondo argomento della funzione (che non possiede un valore di default); e` invece interessante il terzo (Foo('c');): apparentemente potrebbe sembrare un errore, in realta` quello che il compilatore fa e` convertire il parametro attuale 'c' di tipo char in uno di tipo int e chiamare la funzione sostituendo al primo parametro il risultato della conversione di 'c' al tipo int. La conversione di tipo sara` oggetto di una apposita appendice.

 

 

successivo
–«  INDICE  »–

 

 

 

 
Powered by paper&pencil (carta&matita ) - Copyright © 2001-2022 Cataldo Sasso