Skip to content

Incapsulamento, Classi e Metodi

Le classi “POD” (struct pure di soli dati) sono utili per creare agglomerati di variabili. Tuttavia, progettare software su larga scala usando solo dati nudi genera caos e dipendenze ovunque.

Il C++ offre il paradigma dell’Incapsulamento (Encapsulation): un pattern architetturale che collega indissolubilmente i dati con le funzioni che li manipolano. Questo migliora il codice in due modi:

  1. Raggruppa i concetti. Non hai più dati separati dalle funzioni; l’oggetto modella sia il suo stato che come esso varia.
  2. Permette l’Occultamento delle Informazioni (Information Hiding). Puoi impedire ad altro codice di manipolare i dati grezzi interni, forzandolo a passare tramite regole precise.

I metodi non sono altro che funzioni definite all’interno del corpo di una classe (o struct). Poiché vivono dentro l’oggetto, i metodi possiedono un accesso speciale e automatico a tutti i membri dati dell’oggetto stesso.

struct Orologio {
int anno;
// Questo è un metodo!
void aggiungi_anno() {
anno = anno + 1; // Accede direttamente alla variabile 'anno'
}
};

Per chiamare il metodo su un’istanza dell’oggetto si utilizza sempre l’operatore punto (.):

Orologio mio_orologio;
mio_orologio.anno = 2026;
mio_orologio.aggiungi_anno(); // Ora l'anno è 2027

L’Occultamento delle Informazioni (Information Hiding) si attua tramite i controlli di accesso. In C++ ce ne sono due fondamentali:

  • public: Qualsiasi parte del programma può leggere o modificare liberamente il membro. (Nelle struct, tutti i membri sono public di default).
  • private: Il membro è totalmente inaccessibile dall’esterno. Può essere letto o manipolato esclusivamente dai metodi interni della classe stessa.

Immaginiamo di voler impedire che l’anno dell’orologio possa mai essere impostato a un valore inferiore al 2019. Se la variabile anno è pubblica, chiunque potrebbe scrivere mio_orologio.anno = 1990; corrompendo la logica di business. Rendiamola privata e creiamo dei Setter e Getter:

struct OrologioSicuro {
void aggiungi_anno() {
anno++;
}
// Metodo Setter con validazione dei dati
bool set_anno(int nuovo_anno) {
if (nuovo_anno < 2019) {
return false; // Rifiuta la modifica!
}
anno = nuovo_anno;
return true;
}
// Metodo Getter per leggere il valore senza poterlo forzare
int get_anno() {
return anno;
}
private:
// Questa variabile non può più essere toccata dall'esterno!
int anno;
};

In C++, la parola chiave class funziona in modo pressoché identico a struct.

L’unica, cruciale, differenza tecnica tra le due è il livello di accesso predefinito:

  • In una struct, tutto ciò che dichiari è public di default.
  • In una class, tutto ciò che dichiari è private di default, a meno che tu non scriva esplicitamente public:.

Dichiarare OrologioSicuro usando class apparirebbe così:

class OrologioSicuro {
int anno; // E' private di default!
public: // Tutto ciò che segue sarà esposto all'esterno
void aggiungi_anno() { ... }
bool set_anno(int nuovo_anno) { ... }
int get_anno() { ... }
};

La scelta tra class o struct è puramente stilistica. Molte guide stilistiche aziendali usano struct esclusivamente per i POD (dati nudi senza metodi complessi) e class per i tipi completamente incapsulati.

Completa la classe OrologioSicuro. Implementa la logica del metodo set_anno affinché scarti i valori inferiori a 2019 e aggiorni il valore in caso contrario.