Le funzioni nel C++

Dall'introduzione del post precedente abbiamo imparato che la definizione di una funzione è composta dal nome della funzione preceduto dal tipo restituito (o da void, se la funzione non restituisce niente) e seguito da delle parentesi tonde che contengono delle variabili, dette parametri, nelle quali vengono memorizzati i dati passati alla funzione (detti parametri) nel momento in cui viene richiamata; abbiamo imparato che ci possono essere uno o più parametri, o addirittura nessuno; abbiamo imparato che la funzione ha un suo blocco di codice delimitato da delle parentesi graffe; abbiamo imparato infine che una funzione può restituire un risultato, che dev'essere dello stesso tipo che precede il nome della funzione.

Una funzione può essere rappresentata come una scatola chiusa, che riceve qualcosa in ingresso e restituisce qualcos'altro in uscita:

dati in ingresso->|_funzione_|->dati in uscita

La scatola chiusa è il blocco di codice racchiuso tra le parentesi graffe, i dati in ingresso sono quelli passati tramite le parentesi tonde, mentre i dati in uscita sono quelli restituiti tramite l'istruzione return.

Abbiamo poi imparato come richiamare, e cioé come utilizzare, una funzione scritta precedentemente:

variabile_che_raccoglie_risultato = nome_funzione(valori_in_ingresso);

I valori in ingresso sono quelli che vogliamo manipolare, e vengono assegnati alle variabili presenti all'interno delle parentesi tonde nella dichiarazione della variabile.
Richiamando la funzione in questo modo:

funzione(33, "trentini");

La funzione riceve i due valori in ingresso e li attribuisce ai suoi parametri

funzione(int parametro1, string parametro2)
{

parametro1 sarà uguale a 33, mentre parametro2 sarà uguale a "trentini".
Notate come i valori passati siano un intero e una stringa, proprio come i parametri della funzione.

I due parametri, che da questo momento in poi hanno assunto i due valori passatigli tramite la funzione, possono essere utilizzati all'interno del codice racchiuso tra parentesi graffe.

Infine la funzione restituirà un risultato tramite l'istruzione return:

varRisultato = funzione(33, "trentini");

La variabile varRisultato raccoglie il valore restituito da funzione().

Tuttavia abbiamo visto che le funzioni possono essere richiamate ovunque, ad esempio all'interno di un while o di un if:

if( funzione(variabile1) > 0)

si legge come:

"SE il valore restituito da funzione E' maggiore di 0"

Questo può confondere, almeno all'inizio.
Può essere utile, quando si richiama una funzione, sostituirla mentalmente con il valore restituito, così da avere le idee più chiare.

Ad esempio, la nostra funzione collisione() del post precedente può essere richiamata così:

if(!collisione(oggetto1, oggetto2))

Ricordiamo che l'operatore NOT nega il risultato, quindi va letto come " NON E' ":

"SE il risultato restituito da lla funzione NON E' true"

Ricordiamo anche che questa sintassi condensata funziona solo per i tipi boleani, mentre per gli altri tipi bisogna utilizzare per forza una sintassi estesa:

if(etàCliente("mario rossi") != 100)

A occhio può creare confusione, ma se sostituiamo alla funzione un valore ipotetico tra quelli che può restituire (ne scegliamo uno a caso, ci serve solo a livello mentale per leggere meglio la funzione), il significato della linea di codice ci appare subito più chiaro.
Immaginiamo ad esempio che Mario Rossi, il cliente del nostro ricovero, abbia 93 anni.
Ovviamente noi non lo sappiamo, è proprio per questo che richiamiamo la funzione, ma ipotizziamo un'età a caso solo per leggere la linea di codice sotto un'altra luce:

if(93 != 100)

In questo modo capiamo subito il significato dell'if: la funzione restituisce un'età e l'if non fa altro che sostituire la funzione con il risultato restituito e confrontarla con 100; se l'età restituita è diversa da 100 viene eseguito il codice del blocco if.

Lo stesso metodo può essere utilizzato ovunque.
Ad esempio, chi vede per la prima volta una riga di codice del genere:

varRisultato = funzioneSomma(100, 90); //la funzione restituisce un intero

può chiedersi, cosa succede alla variabile varRisultato? Ma basta sostituire la funzione richiamata ad un ipotetico risultato restituito (qui essendo una semplice somma possiamo arrivarci anche da soli :) ) e tutto sarà più chiaro:

varRisultato = 190; //sostituiamo la funzione con un intero+

Ora è chiaro cosa succede! funzioneSomma() restituisce un intero, che viene assegnato a varRisultato.

Oppure, sapreste dirmi cosa succede in questa riga di codice?

cout << funzioneSomma(varNum1, varNum2);

Facciamo la sostituzione della funzione con un valore a caso, purché coerente con il tipo restituito dalla funzione stessa (in questo caso un int):

cout << 93;

Il cout non fa altro che stampare il valore restituito dalla funzione.

Una funzione può anche essere richiamata all'interno di un'altra funzione, ad esempio:

vRisultato = fSottr( fSomma(9, 3), fSomma(5, 6) );

fSottr riceve in ingresso due numeri, esegue una sottrazione e restituisce il risultato, mentre fSomma riceve in ingresso 2 numeri, li somma e restituisce il risultato.
Andiamo a vedere la definizione delle funzioni, e verifichiamo che entrambe restituiscono un int. Proviamo così a sostituirle mentalmente con dei valori che potrebbero restituire, partendo dalle funzioni più interne e muovendoci verso l'esterno:

vRisultato = fSottr( 12 - 11 );

vRisultato = 1;

Le due chiamate a fSomma non fanno altro che sommare due numeri e restituire il risultato della somma; a questo punto fSottr riceverà in ingresso i due risultati restituiti dalle due chiamate a fSomma, eseguirà la sottrazione di questi due valori e restituirà il risultato; infine questo risultato viene assegnato alla variabile vRisultato.

Spero di non avervi confuso ancora più le idee, è importante che abbiate capito bene come si definisce una funzione e come lavora, nonché come richiamare tale funzione e cosa succede quando la si chiama.

Nessun commento:

Posta un commento