Sezione 2.2 
Funzioni (I). 


L'uso di funzioni permette di strutturare il programma in modo modulare, sfruttando tutte le potenzialità fornite dalla programmazione strutturata fornite dal C++.

Una funzione è un blocco di istruzioni con un nome che viene eseguito in ogni punto del programma in cui viene richiamata la funzione usando il nome. Essa si dichiara nel modo seguente:

Tipo Nome ( Argomento1, Argomento2 , ...) Istruzione
dove:
  · Tipo è il tipo del valore ritornato dalla funzione.
  · Nome è il nome con cui possiamo richiamare la funzione.
  · Argomento (possiamo indicarne quanti ne vogliamo, anche nessuno). Un argomento è costituito da un nome di tipo seguito da un  identificatore (ad esempio int x ), esattamente come in una dichiarazione di variabile; ed infatti, all'interno della funzione, un argomento si comporta come una variabile (locale). Gli argomenti permettono di passare dei parametri quando la funzione viene richiamata. I parametri sono separati da virgole.
   ·  Istruzione è il corpo della funzione: un blocco di istruzioni racchiuse tra parentesi graffe {} .

Ecco il primo esempio di funzione:

// esempio di funzione
#include <iostream.h>

int somma (int a, int b)
{
  int r;
  r=a+b;
  return r;
}

int main ()
{
  int z;
  z = somma (5,3);
  cout << "Il risultato e' " << z;
  return 0;
}
Il risultato e' 8

Per esaminare questo codice occorre ricordare quello che abbiamo detto all'inizio del corso: un programma C++ inizia sempre dalla funzione main. Iniziamo quindi dalla funzione main .

La funzione main inizia con la dichiarazione della variabile z di tipo int. Subito dopo vi è una chiamata alla funzione somma. Osserviamo la somiglianza della chiamata alla funzione con l'intestazione della dichiarazione della funzione che si trova un po' più sopra:   

Vi è una chiara corrispondenza: nella funzione main abbiamo richiamato la funzione somma passando, come parametri, i due valori 5 e 3 che corrispondono agli argomenti int a ed int b nella dichiarazione della funzione somma .          

Quando la funzione somma viene richiamata dal  main, il controllo passa dalla funzione main alla funzione somma. I valori 5 e 3 passati come parametri vengono copiati nelle due variabili int a ed int b locali alla funzione somma .   

La funzione somma dichiara una nuova variabile (int r; ), e quindi, con l'istruzione r=a+b;, assegna ad r  il risultato di a più b . Siccome i valori passati come parametri sono 5 per a e 3 per b, il risultato è 8 .

L'istruzione:

return r;
infine termina la funzione somma e ritorna alla    funzione    che l'aveva richiamate (la funzione main ) riprendendo    l'esecuzione  dal punto in cui era stata interrotta con la chiamata somma(5,3) . L'istruzione return  ha come argomento     la variabile r ( return r;  ), che al momento dell'esecuzione della return ha valore 8; di conseguenza 8 è il valore ritornato dalla   funzione.
Il valore ritornato con l'istruzione return è il valore che viene attribuito alla funzione quando essa viene valutata. Ed è proprio tale valore (ossia 8) che viene assegnato alla variabile z.

La riga seguente di main è:

cout << "Il risultato e' " << z;
che, come sappiamo, stampa il risultato sullo schermo.

Scopo delle variabili                

Il campo di validità (scopo) delle variabili dichiarate in una funzione o in un blocco di istruzioni è limitato alla funzione stessa e al blocco di istruzioni e quindi tale variabile non può essere usata al di fuori di tale ambito. Nell'esempio precedente non sarebbe possibile usare le variabili a , b ed r nella funzione main in quanto esse sono locali alla funzione somma. Analogamente non sarebbe possibile usare la variabile z direttamente nella funzione somma in quanto essa è locale alla funzione main.

Pertanto lo scopo delle variabili locali è limitato al livello di annidamento in cui esse sono dichiarate. Si possono anche dichiarare delle variabili globali che sono visibili in qualunque punto del programma, dentro o fuori a qualsiasi funzione. Per questo occorre dichiarare le variabili globali al di fuori di ogni funzione o blocco, ossia direttamente nel corpo del programma.

Ed ecco un altro esempio sulle funzioni:


// esempio di funzioni
#include <iostream.h>
int sottrazione (int a, int b)
{
  int r;
  r=a-b;
  return r;
}

int main ()
{
  int x=5, y=3, z;
  z = sottrazione (7,2);
  cout << "Il primo risultato e' " << z << '\n';
  cout << "Il secondo risultato e' " << sottrazione (7,2) << '\n';
  cout << "Il terzo risultato e' " << sottrazione (x,y) << '\n';
  z = 4 + sottrazione (x+2,y);
  cout << "Il quarto risultato e' " << z << '\n';
  return 0;
}
Il primo risultato e' 5
Il secondo risultato e' 5
Il terzo risultato e' 2

Il quarto risultato e' 8

In questo caso abbiamo creato la funzione sottrazione . L'unica cosa che fa questa funzione è sottrarre i due valori passati come parametro e restituire il risultato.

Se esaminiamo la funzione main vediamo che vengono effettuate diverse chiamate alla funzione sottrazione . Abbiamo usato diversi modi per chiamare la funzione per illustrare cosa succede quando una funzione viene chiamata. 

Il funzionamento di una semplice funzione come sottrazione si può descrivere dicendo che l'effetto di una chiamata a tale funzione è lo stesso che si ottiene sostituendo la chiamata con il suo risultato.  Ad esempio, nel primo caso:

z = sottrazione (7,2);
cout << "Il primo risultato e' " << z;
se sostituiamo la chiamata di funzione con il suo risultato (cioè con 5), otteniamo: 
z = 5;
cout << "Il primo risultato e' " << z;
Analogamente
cout << "Il secondo risultato e' " << sottrazione (7,2);
ha lo stesso effetto della chiamata precedente, ma questa volta la chiamata a sottrazione viene usata direttamente come argomento dell'operatore di inserimenti (<<) nel flusso cout . Sostituendo la chiamata con il suo risultato si ottiene: 
cout << "Il secondo risultato e' " << 5;
in quanto 5 è il risultato di sottrazione (7,2) .

Nel caso:

cout << "Il terzo risultato e' " << sottrazione (x,y);
l'unica novità è che i parametri della chiamata a sottrazione sono delle variabili invece che delle costanti. In questo caso i valori passati alla funzione sono i valori delle variabili x ed y , che sono appunto 5 e 3 ed il risultato che si ottiene è 2

Nel quarto caso

z = 4 + sottrazione (x+2,y);
il primo dei due parametri è una espressione x+2 ed è il suo valore 7 che viene passato come parametro alla funzione. Il risultato è in questo caso 4 che sostituito al posto della chiamata di funzione fornisce:
z = 4 + 4;

Funzioni senza risultato. L'uso di void .

Ricordiamo la sintassi di una dichiarazione di funzione: 
Tipo Nome ( Argomento1, Argomento2 , ...) Istruzione
si vede che è necessario che essa inizi con un nome di Tipo , ossia con il tipo di dato che deve essere ritornato dalla funzione con l'istruzione return. E se non vogliamo ritornare alcun valore?

Supponiamo di voler scrivere una funzione che deve soltanto scrivere qualcosa sullo schermo. Non ci serve che essa ritorni un valore e neppure abbiamo bisogno di passargli dei parametri. Allo scopo il C fornisce un particolare tipo void. Osserviamo il seguente esempio:

// esempio di funzione void
#include <iostream.h>

void stampa (void)
{
  cout << "Sono una funzione!";
}

int main ()
{
  stampa ();
  return 0;
}
Sono una funzione!

In C++ l'indicazione di void come tipo del risultato o come parametro si può omettere scrivendo semplicemente stampa (). L'uso esplicito di void è comunque consigliato per indicare chiaramente che non è richiesto un risultato e/o non sono richiesti parametri (e che quindi non ci si è semplicemente dimenticati di indicarli).

Dobbiamo ricordare che una chiamata di funzione è costituita dal nome della funzione seguita dai parametri racchiusi tra parentesi.  Il fatto che non ci siano argomenti non ci esime dal dover scrivere la coppia di parentesi. Di conseguenza la chiamata alla funzione stampa è: 

stampa ();
il che indica chiaramente che si tratta di una chiamata di funzione e non del nome di una variabile o di qualcosa d'altro.

           
Precedente:
2-1. Strutture di controllo.

indice
Seguente:
2-3. Funzioni (II).