- Comprendere la differenza tra interfaccia pubblica e implementazione privata
- Applicare i modificatori di accesso per proteggere l'integrità dei dati di un oggetto
- Realizzare metodi di interazione (interruttori logici) per modificare lo stato degli oggetti
- Modellare una classe basata su requisiti di sicurezza del mondo reale
Nella programmazione orientata agli oggetti (OOP), uno dei concetti fondamentali è l’incapsulamento, ovvero la capacità di nascondere i dettagli interni di una classe e di esporre solo ciò che è necessario all’esterno. In C++, questo principio viene realizzato tramite i modificatori di accesso (o access specifiers), che permettono di controllare la visibilità e l’accessibilità dei membri di una classe, come variabili e metodi.
I principali modificatori di accesso in C++ sono public, private e protected. Essi stabiliscono da quali parti del programma è possibile accedere ai membri di una classe: dall’interno della classe stessa, dalle classi derivate o dal codice esterno. L’uso corretto dei modificatori di accesso consente di scrivere codice più sicuro, modulare e facile da mantenere, riducendo il rischio di modifiche indesiderate allo stato interno degli oggetti.
Comprendere il funzionamento dei modificatori di accesso è quindi essenziale per progettare classi ben strutturate e per sfruttare appieno i principi della programmazione orientata agli oggetti in C++.
Cosa significa davvero "Accedere" a un dato?
In programmazione, accedere significa due cose molto semplici:
- Leggere: Vedere cosa c'è scritto in una variabile (es. cout << oggetto.prezzo;).
- Scrivere: Cambiare il valore di una variabile (es. oggetto.prezzo = 10;).
Chi è che "Accede"?
Immaginiamo che il nostro programma sia diviso in due zone:
- 1. "Dentro la Classe" (I Metodi): Immagina di essere dentro il codice della classe stessa. Qui sei "a casa tua". Hai le chiavi di tutte le stanze.
Cosa puoi fare: Puoi toccare tutto. Le variabili private, public e protected sono tutte a tua disposizione. - 2. "Fuori dalla Classe" (Il mondo esterno / Il main): Immagina di essere nel main o in un'altra funzione esterna. Qui sei un ospite (o un utente).
Cosa puoi fare: Puoi toccare solo ciò che è stato lasciato "in giardino" o "all'ingresso", ovvero ciò che è public. Non puoi entrare nelle stanze private.
Proviamo a vedere chi riesce a toccare la variabile temperatura in questo scenario:
class Caldaia {
private:
int temperatura; // Questa è privata!
public:
void imposta(int t) {
// QUI SIAMO "DENTRO": l'accesso è permesso.
temperatura = t;
}
};
int main() {
Caldaia miaCaldaia;
// CHI ACCEDE QUI? Il main (mondo esterno).
// miaCaldaia.temperatura = 80;
// ERRORE! Il main è "fuori" e prova a toccare un dato "private".
miaCaldaia.imposta(80);
// FUNZIONA! Il main usa un metodo public (il pulsante)
// che a sua volta ha il permesso di toccare la variabile interna.
}
- Se metti
public, stai dicendo al main: "Prendi pure questa variabile, fai quello che vuoi". - Se metti
private, stai dicendo al main: "Tu non puoi toccare questo dato. Se vuoi modificarlo, devi chiedere a me usando le mie funzioni pubbliche".
Esempio: Il profilo Social (Gestione Password)
Qui vediamo come il modificatore private protegga un dato che non deve mai essere letto dall'esterno, nemmeno per sbaglio.
class ProfiloSocial {
private:
string password; // Nessuno da fuori deve poter leggere la password
public:
string nomeUtente; // Il nome è pubblico, tutti possono vederlo
ProfiloSocial(string user, string pass) {
nomeUtente = user;
password = pass;
}
// Metodo per cambiare password in sicurezza
void cambiaPassword(string vecchia, string nuova) {
if (vecchia == password) {
password = nuova;
cout << "Password aggiornata con successo!" << endl;
} else {
cout << "Vecchia password errata. Accesso negato." << endl;
}
}
};
int main() {
ProfiloSocial mioProfilo("MarioRossi99", "12345");
// ACCESSO AL NOME (Public)
cout << "Utente: " << mioProfilo.nomeUtente << endl; // FUNZIONA
// ACCESSO ALLA PASSWORD (Private)
// cout << mioProfilo.password;
// ERRORE: Sarebbe un grave rischio di sicurezza se il main potesse leggere il dato private!
mioProfilo.cambiaPassword("12345", "nuova_pass_sicura"); // FUNZIONA
}
LABORATORIO
Sistema di Controllo Drone
Obiettivo: Modellare un drone professionale dove l'altitudine e il seriale sono protetti da modifiche esterne non autorizzate, garantendo la sicurezza del volo.
- Editor di codice C++ (Code::Blocks, VS Code, ecc.)
- Compilatore GCC
1 Progettazione della Classe
Definiamo i dati sensibili in private. L'altitudine non può essere cambiata dal pilota scrivendo un numero nel main, ma solo chiamando il metodo decolla().
#include <iostream>
#include <string>
using namespace std;
class Drone {
private:
// DATI PROTETTI: Il main non può vederli né cambiarli
string seriale;
int altitudine;
bool motoriAttivi;
public:
// Costruttore: Inizializza il drone a terra
Drone(string s) {
seriale = s;
altitudine = 0;
motoriAttivi = false;
}
// AZIONI PUBBLICHE: I pulsanti del radiocomando
void avviaMotori() {
motoriAttivi = true;
cout << "Motori avviati correttamente." << endl;
}
void decolla() {
if (motoriAttivi) {
altitudine = 5; // Solo la classe può cambiare l'altitudine
cout << "Decollo completato. Quota: 5 metri." << endl;
} else {
cout << "ERRORE: Impossibile decollare con motori spenti!" << endl;
}
}
void stampaStato() {
cout << "--- STATUS DRONE ---" << endl;
cout << "S/N: " << seriale << endl;
cout << "Altitudine: " << altitudine << "m" << endl;
cout << "Motori: " << (motoriAttivi ? "ON" : "OFF") << endl;
}
};
2 Test nel Main: Verifica dei Permessi
Implementiamo il test. Provate a forzare l'altitudine dal main per vedere come reagisce il compilatore.
int main() {
Drone mioDrone("DRONE-A1");
// OPERAZIONI CONSENTITE (Public)
mioDrone.stampaStato();
mioDrone.avviaMotori();
mioDrone.decolla();
mioDrone.stampaStato();
// OPERAZIONI NEGATE (Private) - Togli il commento per testare l'errore
// mioDrone.altitudine = 100;
// mioDrone.seriale = "HACKED";
return 0;
}
3 Perché è importante?
Riflettiamo sul "chi" accede:
- Il Seriale è privato: garantisce che l'identità del drone non venga manomessa dopo l'accensione.
- L'Altitudine è privata: evita che un programmatore distratto porti il drone a 1000 metri istantaneamente dal main, causandone lo schianto. Il valore cambia solo tramite logica sicura (
decolla).
4 Esercitazione Autonoma: Sicurezza Avanzata
Espandi il codice aggiungendo queste funzionalità:
- Atterraggio: Aggiungi un metodo pubblico
atterra()che porti l'altitudine a 0 e spenga i motori, ma solo se l'altitudine attuale è maggiore di zero. - Livello Batteria: Aggiungi un attributo
batteria(int). Il metododecolla()deve funzionare solo se la batteria è superiore al 20%. - Controllo Manuale: Crea un metodo
setQuota(int q). Deve permettere di cambiare l'altitudine solo se il valoreqè compreso tra 0 e 50 metri. Se il valore è fuori range, stampa un avviso di sicurezza.