Vai al contenuto

Le funzioni

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! 🚀

Esercitazioni Pratiche C++

Metti in pratica ciò che hai imparato con queste esercitazioni complete

Tutte le Esercitazioni

📊 Variabili e Tipi di Dato

➕ Operatori Matematici e Logici in C++

🔀 Strutture di controllo condizionali

🔄 I cicli in C++

🗃️ C++ gli array

⚙️ Le funzioni in C++

📈 Ordinamento dei Dati

🏗️ Le struct in C++

🎯 I puntatori

🧩 La Programmazione Orientata agli Oggetti (OOP)

📁 La gestione dei file in C++

💪 Esercizi C++ Raccolta Completa

12 esercitazioni complete per padroneggiare il C++