Funzioni in C++

Organizza il codice in moduli riutilizzabili e migliora la leggibilità

Le funzioni sono blocchi di codice che permettono di organizzare il programma in moduli riutilizzabili, rendendo il codice più leggibile, modulare e facilitandone la manutenzione.

1. Definizione e Dichiarazione di Funzioni

📌 Perché usare le funzioni: Riutilizzo del codice, organizzazione, debugging più semplice e manutenzione facilitata.

1️⃣ Dichiarazione (Prototipo)

Informa il compilatore su nome, tipo di ritorno e parametri della funzione.

tipo nomeFunzione(tipo param1, tipo param2);

2️⃣ Definizione (Implementazione)

Contiene il codice effettivo che viene eseguito quando la funzione è chiamata.

tipo nomeFunzione(tipo param1, tipo param2) { ... }

1.1 Dichiarazione

// Sintassi dichiarazione
tipoDiRitorno nomeFunzione(tipo parametro1, tipo parametro2, …);
// Esempi pratici
int somma(int a, int b);
double calcolaArea(double base, double altezza);
void stampaMessaggio(string testo);

1.2 Definizione

// Sintassi definizione
tipoDiRitorno nomeFunzione(tipo parametro1, tipo parametro2, …) {
// corpo della funzione
return valore; // se il tipo di ritorno non è void
}
// Esempi pratici
int somma(int a, int b) {
return a + b;
}
double calcolaArea(double base, double altezza) {
return base * altezza;
}
void stampaMessaggio(string testo) {
cout << testo << endl;
// Nessun return per funzioni void
}

2. Valore di Ritorno e Parametri

📌 Tipi di ritorno: int, double, string, bool, void (nessun ritorno), o qualsiasi tipo definito.

2.1 Valore di Ritorno

// Funzione con valore di ritorno
double areaRettangolo(double lunghezza, double larghezza) {
return lunghezza * larghezza;
}
// Funzione senza valore di ritorno (void)
void saluta(string nome) {
cout << “Ciao, “ << nome << “!” << endl;
// Nessuna istruzione return necessaria
}

2.2 Tipi di Passaggio Parametri

✅ Per Valore

Vantaggio: Sicuro, la variabile originale non viene modificata

Svantaggio: Copia dei dati (overhead per oggetti grandi)

void funzione(int a)

🔗 Per Riferimento

Vantaggio: Efficiente, modifica la variabile originale

Svantaggio: Può modificare dati inaspettatamente

void funzione(int &a)

🛡️ Riferimento Costante

Vantaggio: Efficiente e sicuro

Svantaggio: Non permette modifiche

void funzione(const int &a)

// Esempio passaggio per riferimento
void scambia(int &a, int &b) {
int temp = a;
a = b;
b = temp;
}
// Esempio passaggio per valore
int raddoppia(int numero) {
return numero * 2;
// La variabile originale non viene modificata
}

3. Scope delle Variabili

⚠️ Importante: Limitare l’uso di variabili globali per evitare conflitti e rendere il codice più chiaro.

📍 Variabili Locali

Scope: Solo nel blocco dove sono dichiarate

Vita: Finché il blocco è attivo

Accesso: Limitato al blocco

void funzione() { int locale; }

🌍 Variabili Globali

Scope: Tutto il file/programma

Vita: Durata del programma

Accesso: Da qualsiasi funzione

int globale; int main() { }

3.1 Variabili Locali

void funzioneEsempio() {
int locale = 10; // variabile locale
cout << “Valore locale: “ << locale << endl;
}
// La variabile ‘locale’ non è accessibile qui – ERRORE!

3.2 Variabili Globali

int globale = 100; // variabile globale
void funzioneVisualizza() {
cout << “Valore globale: “ << globale << endl;
}
int main() {
funzioneVisualizza(); // Output: 100
globale = 200; // Modifica la variabile globale
funzioneVisualizza(); // Output: 200
return 0;
}

🎯 Esempi Pratici

Esercizi guidati per comprendere meglio le funzioni

4.1 Massimo tra Due Numeri

#include <iostream>
using namespace std;
// Dichiarazione della funzione
int massimo(int a, int b);
int main() {
int num1 = 15, num2 = 27;
cout << “Il massimo tra “ << num1 << ” e “ << num2;
cout << ” è: “ << massimo(num1, num2) << endl;
return 0;
}
// Definizione della funzione
int massimo(int a, int b) {
if (a > b)
return a;
else
return b;
}

4.2 Scambio di Variabili (Passaggio per Riferimento)

#include <iostream>
using namespace std;
void scambia(int &a, int &b);
int main() {
int x = 5, y = 10;
cout << “Prima dello scambio: x = “ << x << “, y = “ << y << endl;
scambia(x, y);
cout << “Dopo lo scambio: x = “ << x << “, y = “ << y << endl;
return 0;
}
void scambia(int &a, int &b) {
int temp = a;
a = b;
b = temp;
}

💡 Spiegazione:
• Le variabili x e y vengono modificate direttamente
• Il passaggio per riferimento permette di alterare le variabili originali
• La variabile temp è locale alla funzione

4.3 Scope delle Variabili

#include <iostream>
using namespace std;
int globale = 50; // variabile globale
void visualizzaVariabili() {
int locale = 25; // variabile locale
cout << “Variabile globale: “ << globale << endl;
cout << “Variabile locale: “ << locale << endl;
}
int main() {
visualizzaVariabili();
// La seguente riga causerebbe errore perché ‘locale’ non è visibile in main:
// cout << locale; // ERRORE!
return 0;
}

5. Esercizi Pratici

Esercizio 1: Calcolo della Media di un Array

#include <iostream>
using namespace std;
double calcolaMedia(int array[], int dimensione) {
int somma = 0;
for (int i = 0; i < dimensione; i++) {
somma += array[i];
}
return static_cast<double>(somma) / dimensione;
}
int main() {
int numeri[] = {10, 20, 30, 40, 50};
int dimensione = sizeof(numeri) / sizeof(numeri[0]);
cout << “La media è: “ << calcolaMedia(numeri, dimensione) << endl;
return 0;
}

Esercizio 2: Verifica Numero Pari

#include <iostream>
using namespace std;
bool isPari(int n) {
// Restituisce true se n è divisibile per 2, altrimenti false
return (n % 2 == 0);
}
int main() {
int numero;
cout << “Inserisci un numero: “;
cin >> numero;
if (isPari(numero))
cout << numero << ” è pari.” << endl;
else
cout << numero << ” è dispari.” << endl;
return 0;
}

💡 Spiegazione:
• La funzione restituisce un valore booleano (true/false)
• L’operatore modulo % restituisce il resto della divisione
• Se il resto è 0, il numero è pari

Esercizio 3: Fattoriale Ricorsivo

#include <iostream>
using namespace std;
int fattoriale(int n) {
// Caso base
if (n <= 1)
return 1;
// Caso ricorsivo
else
return n * fattoriale(n – 1);
}
int main() {
int numero;
cout << “Inserisci un numero per calcolare il fattoriale: “;
cin >> numero;
cout << “Il fattoriale di “ << numero << ” è: “ << fattoriale(numero) << endl;
return 0;
}

💡 Spiegazione Ricorsione:
Caso base: fattoriale(1) = 1 – ferma la ricorsione
Caso ricorsivo: fattoriale(n) = n × fattoriale(n-1)
• Ogni chiamata risolve un problema più piccolo

6. Esercizi Avanzati

Esercizio 4: Contatore con Variabile Static

#include <iostream>
using namespace std;
int contatore() {
static int count = 0; // Variabile statica – mantiene il valore tra le chiamate
count++;
return count;
}
int main() {
cout << “Chiamata 1: “ << contatore() << endl; // Output: 1
cout << “Chiamata 2: “ << contatore() << endl; // Output: 2
cout << “Chiamata 3: “ << contatore() << endl; // Output: 3
return 0;
}

Esercizio 5: Overloading di Funzioni

#include <iostream>
using namespace std;
// Stesso nome, parametri diversi
int somma(int a, int b) {
return a + b;
}
double somma(double a, double b) {
return a + b;
}
string somma(string a, string b) {
return a + b;
}
int main() {
cout << “Somma interi: “ << somma(5, 3) << endl; // 8
cout << “Somma double: “ << somma(5.5, 3.2) << endl; // 8.7
cout << “Somma stringhe: “ << somma(“Ciao “, “Mondo”) << endl; // “Ciao Mondo”
return 0;
}

Conclusioni

Riassunto dei concetti chiave:

✅ Definizione e Dichiarazione

Le funzioni permettono di incapsulare logica e operazioni in blocchi riutilizzabili

✅ Valore di Ritorno e Parametri

È possibile passare dati alle funzioni e restituire risultati usando diversi tipi di passaggio

✅ Scope delle Variabili

Le variabili locali esistono solo nel loro blocco, mentre quelle globali sono accessibili ovunque

Questi esempi ed esercizi pratici ti aiuteranno a comprendere in profondità come lavorare con funzioni e scope in C++, offrendoti una base solida per sviluppare programmi modulari ed efficienti. Buon coding! 🚀

Torna in alto