Organizzazione del Codice
Organizzare il codice in più file
Sezione intitolata “Organizzare il codice in più file”Quando scrivi un programma piccolo, un unico file .cpp va benissimo. Ma immagina di dover scrivere un gestionale scolastico con centinaia di funzioni: tutto in un file solo sarebbe un disastro. Trovare una funzione richiederebbe minuti.
Dividere il codice in più file risolve questo problema. Ogni file ha uno scopo preciso, come i capitoli di un libro.
Vantaggi:
- Leggibilità: ogni file è focalizzato su un argomento
- Riutilizzo: puoi usare le stesse funzioni in più programmi
- Manutenzione: modifichi una parte senza toccare il resto
- Collaborazione: più persone lavorano su file diversi senza interferirsi
I due tipi di file
Sezione intitolata “I due tipi di file”In C++ il codice viene diviso in due tipi di file:
| Tipo | Estensione | Cosa contiene |
|---|---|---|
| Header | .h o .hpp | Le dichiarazioni (cosa esiste) |
| Implementazione | .cpp | Le definizioni (come funziona) |
Il file header è come il sommario di un libro: ti dice cosa c’è, ma non ti mostra tutto il contenuto. Il file .cpp è il contenuto vero e proprio.
Esempio pratico
Sezione intitolata “Esempio pratico”Immaginiamo di creare una piccola libreria con funzioni matematiche personalizzate.
Struttura dei file
Sezione intitolata “Struttura dei file”progetto/├── main.cpp├── matematica.h└── matematica.cppIl file header: matematica.h
Sezione intitolata “Il file header: matematica.h”Contiene solo le firme delle funzioni (senza il corpo):
// matematica.h — le dichiarazioni
#ifndef MATEMATICA_H // protezione dall'inclusione multipla (spiegata più sotto)#define MATEMATICA_H
int somma(int a, int b);int prodotto(int a, int b);double potenza(double base, int esponente);
#endifIl file di implementazione: matematica.cpp
Sezione intitolata “Il file di implementazione: matematica.cpp”Contiene il codice vero delle funzioni:
// matematica.cpp — le implementazioni
#include "matematica.h" // include il proprio header
int somma(int a, int b) { return a + b;}
int prodotto(int a, int b) { return a * b;}
double potenza(double base, int esponente) { double risultato = 1.0; for (int i = 0; i < esponente; i++) { risultato *= base; } return risultato;}Il file principale: main.cpp
Sezione intitolata “Il file principale: main.cpp”Include l’header per sapere che le funzioni esistono:
#include <iostream>#include "matematica.h" // include il nostro header (virgolette, non <>)using namespace std;
int main() { cout << "Somma: " << somma(3, 4) << endl; cout << "Prodotto: " << prodotto(3, 4) << endl; cout << "2^8 = " << potenza(2, 8) << endl; return 0;}Per compilare, passa tutti i file .cpp al compilatore:
g++ main.cpp matematica.cpp -o programma./programmaLe include guard: protezione dall’inclusione multipla
Sezione intitolata “Le include guard: protezione dall’inclusione multipla”Nell’header hai visto queste righe “strane”:
#ifndef MATEMATICA_H#define MATEMATICA_H
// ... contenuto ...
#endifSi chiamano include guard. Servono a evitare un errore comune: se lo stesso header venisse incluso due volte nello stesso file, il compilatore si lamenterebbe di funzioni “ridefinite”.
Come funzionano:
#ifndef MATEMATICA_H— “se MATEMATICA_H non è ancora definito…”#define MATEMATICA_H— “…definiscilo…”- “…ed esegui tutto questo contenuto”
#endif— fine del blocco
La seconda volta che il file viene incluso, MATEMATICA_H è già definito, quindi tutto il contenuto viene saltato automaticamente.
Alternativa moderna: #pragma once
Sezione intitolata “Alternativa moderna: #pragma once”#pragma once // includi questo file una sola volta
// contenuto dell'header...#pragma once fa la stessa cosa delle include guard, ma è più semplice da scrivere. È supportata da tutti i compilatori moderni.
Come includere file
Sezione intitolata “Come includere file”Ci sono due sintassi per #include:
#include <iostream> // parentesi angolari → librerie di sistema#include "matematica.h" // virgolette → file del tuo progettoEsempio con una classe
Sezione intitolata “Esempio con una classe”Le classi si dividono esattamente nello stesso modo: la dichiarazione nell’header, i metodi nel .cpp.
studente.h
Sezione intitolata “studente.h”#pragma once
#include <string>using namespace std;
class Studente {private: string nome; int eta; double votoMedio;
public: Studente(string n, int e); // solo le firme dei metodi void aggiungiVoto(double voto); void stampaInfo() const; string getNome() const; double getVotoMedio() const;};studente.cpp
Sezione intitolata “studente.cpp”#include "studente.h"#include <iostream>using namespace std;
// L'implementazione dei metodi usa NomeClasse:: davanti al nome del metodoStudente::Studente(string n, int e) { nome = n; eta = e; votoMedio = 0.0;}
void Studente::aggiungiVoto(double voto) { if (votoMedio == 0.0) { votoMedio = voto; } else { votoMedio = (votoMedio + voto) / 2.0; }}
void Studente::stampaInfo() const { cout << "Nome: " << nome << ", Eta: " << eta << ", Media: " << votoMedio << endl;}
string Studente::getNome() const { return nome; }double Studente::getVotoMedio() const { return votoMedio; }main.cpp
Sezione intitolata “main.cpp”#include <iostream>#include "studente.h"using namespace std;
int main() { Studente s("Mario", 16); s.aggiungiVoto(8.5); s.aggiungiVoto(7.0); s.aggiungiVoto(9.0); s.stampaInfo(); return 0;}Compilazione:
g++ main.cpp studente.cpp -o programmaCosa va dove
Sezione intitolata “Cosa va dove”Nell’header (.h) metti:
- Le firme delle funzioni (prototipi)
- Le dichiarazioni delle classi
- Le definizioni di
structedenum - Le costanti (
const)
Nel file .cpp metti:
- Il corpo delle funzioni
- Il corpo dei metodi delle classi
- La logica del programma
Regola pratica: se qualcuno ha bisogno di sapere che esiste, mettilo nell’header. Se qualcuno ha bisogno di vedere come funziona, mettilo nel .cpp.
Errori comuni
Sezione intitolata “Errori comuni”// Dimenticare le include guard → errori di ridefinizione// Soluzione: aggiungi #pragma once o #ifndef
// Includere il .cpp invece dell'header#include "matematica.cpp" // SBAGLIATO#include "matematica.h" // CORRETTO
// Dimenticare di compilare tutti i file .cppg++ main.cpp -o programma // SBAGLIATO — manca matematica.cppg++ main.cpp matematica.cpp -o programma // CORRETTO