La programmazione orientata agli oggetti (OOP) è uno dei pilastri fondamentali dello sviluppo software moderno. Attraverso concetti come composizione, aggregazione, associazione ed ereditarietà, è possibile creare sistemi modulari, riutilizzabili e facili da mantenere. In questo articolo, esploreremo una serie di esercizi pratici in C++ che coprono questi concetti, offrendo una guida passo-passo per comprendere e applicare le relazioni tra classi. Che tu sia un principiante o un programmatore esperto, questi esercizi ti aiuteranno a consolidare le tue competenze nella OOP.

  1. Gestione di una Torcia con Batteria scaricabile
    L’esercizio richiede di implementare una classe Torcia che utilizza una Lampadina e una Batteria in composizione. La torcia può essere accesa solo se la batteria ha sufficiente carica. Ogni accensione consuma una unità di carica della batteria. Se la batteria è scarica, la lampadina si spegne automaticamente. Le funzioni da implementare includono il costruttore, l’accensione, lo spegnimento e la verifica dello stato della lampadina.
    Obiettivi Didattici: L’esercizio mira a rafforzare la comprensione della composizione tra classi, la gestione dello stato degli oggetti e l’implementazione di logiche condizionali basate sullo stato interno di un oggetto. Inoltre, introduce il concetto di interdipendenza tra oggetti, dove il comportamento di uno (la lampadina) dipende dallo stato di un altro (la batteria).
  2. Contenitore e Oggetto in composizione, calcolo del peso
    Si deve creare una classe Contenitore che contiene un oggetto di tipo Oggetto. Entrambe le classi hanno un attributo peso. Il compito è implementare un metodo getPeso nella classe Contenitore che restituisca il peso complessivo, sommando il peso del contenitore e quello dell’oggetto al suo interno.
    Obiettivi Didattici: L’esercizio introduce il concetto di composizione, dove un oggetto è parte integrante di un altro. Insegna come gestire la costruzione di oggetti annidati e come calcolare proprietà aggregate basate su più oggetti. Rafforza anche la comprensione della gestione dei costruttori in contesti di composizione.
  3. Torcia con due batterie in composizione
    L’esercizio estende il concetto della torcia introducendo due batterie. La torcia può essere accesa solo se almeno una delle due batterie ha carica. Ogni accensione consuma una carica da una delle due batterie, alternandole. La torcia si spegne definitivamente solo quando entrambe le batterie sono scariche.
    Obiettivi Didattici: Questo esercizio approfondisce la composizione, introducendo la gestione di più oggetti componenti. Insegna come implementare logiche più complesse per la gestione dello stato e come alternare l’uso di risorse multiple (in questo caso, le batterie).
  4. Sistema di monitoraggio della temperatura con due sensori
    Si deve implementare un sistema di monitoraggio della temperatura composto da due sensori. Ogni sensore ha una temperatura massima. Se almeno un sensore è sotto la sua temperatura massima, il sistema stampa “Temperatura sicura”. Se entrambi i sensori superano la temperatura massima, viene stampato “Allerta calore”.
    Obiettivi Didattici: L’esercizio introduce la gestione di più oggetti in un contesto di monitoraggio. Insegna come implementare logiche condizionali basate sullo stato di più oggetti e come gestire la composizione in scenari reali, come il controllo di sistemi complessi.
  5. Composizione tra Auto e Motore
    Si deve implementare una classe Auto che contiene un oggetto di tipo Motore in composizione. Il motore ha attributi come potenza e numero di cilindri, mentre l’auto ha un modello e un colore.
    Obiettivi Didattici: L’esercizio rafforza il concetto di composizione, mostrando come un oggetto complesso (l’auto) sia composto da un oggetto più semplice (il motore). Insegna anche come gestire attributi multipli e come costruire oggetti annidati.
  6. Composizione a cardinalità singola tra due oggetti
    Si deve implementare una relazione di composizione tra due classi, A e B, dove A è l’oggetto composto e B il componente. Il compito è definire il costruttore di A e assicurarsi che il codice nel main possa creare un oggetto di tipo A correttamente.
    Obiettivi Didattici: L’esercizio introduce il concetto di composizione a cardinalità singola, mostrando come un oggetto possa essere parte integrante di un altro. Rafforza la comprensione dei costruttori e della gestione delle dipendenze tra oggetti.
  7. Gestione di una scatola di cancelleria con limite di capacità
    Si deve implementare una classe Scatola che può contenere fino a 5 oggetti di cancelleria (matite o gomme). Gli oggetti possono essere aggiunti solo in posizioni specifiche e non è possibile sovrascrivere oggetti esistenti. Il programma deve permettere di aggiungere oggetti, visualizzare il contenuto della scatola e terminare l’esecuzione.
    Obiettivi Didattici: L’esercizio insegna come gestire array di oggetti e come implementare logiche di controllo per l’aggiunta e la visualizzazione di elementi. Introduce anche il concetto di limiti di capacità e gestione degli errori in contesti di archiviazione.
  8. Aggregazione uno ad uno Torcia – Lampadina
    Si deve implementare una relazione di aggregazione tra una classe Torcia e una classe Lampadina. La torcia deve poter accendere la lampadina, sostituirla e verificare se è accesa.
    Obiettivi Didattici: L’esercizio introduce il concetto di aggregazione, mostrando come un oggetto possa contenere un riferimento a un altro oggetto senza esserne parte integrante. Insegna anche come gestire la sostituzione di oggetti aggregati.
  9. Aggregazione tra Classe Libro e Capitolo
    Si deve implementare una relazione di aggregazione tra una classe Libro e una classe Capitolo. Il libro deve poter calcolare il numero totale di pagine sommando quelle di tutti i capitoli.
    Obiettivi Didattici: L’esercizio rafforza il concetto di aggregazione, mostrando come un oggetto possa contenere più oggetti di un altro tipo. Insegna anche come gestire array o vettori di oggetti e come calcolare proprietà aggregate.
  10. Aggregazione tra due classi
    Si deve implementare una relazione di aggregazione tra una classe A e una classe B. La classe A deve poter contenere un oggetto di tipo B e calcolare un valore basato sui loro attributi.
    Obiettivi Didattici: L’esercizio introduce il concetto di aggregazione facoltativa, mostrando come un oggetto possa contenere un riferimento a un altro oggetto in modo opzionale. Insegna anche come gestire logiche condizionali basate sulla presenza o assenza di un oggetto aggregato.
  11. Associazione tra Università e Studente
    Si deve implementare una relazione di associazione tra una classe Università e una classe Studente. Uno studente può essere associato a un’università, ma non è obbligatorio. Il programma deve permettere di inserire i dati di uno studente e visualizzare le informazioni, inclusa l’università associata.
    Obiettivi Didattici: L’esercizio introduce il concetto di associazione, mostrando come due oggetti possano essere collegati in modo facoltativo. Insegna anche come gestire puntatori e riferimenti in contesti di associazione.
  12. Associazione unidirezionale Persona – Salvadanaio
    Si deve implementare una relazione di associazione unidirezionale tra una classe Persona e una classe Salvadanaio. Una persona può avere un solo salvadanaio e può aggiungere monete fino al riempimento.
    Obiettivi Didattici: L’esercizio rafforza il concetto di associazione unidirezionale, mostrando come un oggetto possa fare riferimento a un altro. Insegna anche come gestire logiche di aggiunta e controllo di risorse limitate.
  13. Associazione bidirezionale tra due Persone
    Si deve implementare una relazione di associazione bidirezionale tra due oggetti di tipo Persona. Quando due persone stringono amicizia, entrambe devono diventare amiche reciprocamente.
    Obiettivi Didattici: L’esercizio introduce il concetto di associazione bidirezionale, mostrando come due oggetti possano riferirsi l’uno all’altro. Insegna anche come gestire relazioni reciproche e aggiornamenti di stato.
  14. Gestione di una libreria
    Si deve completare un codice per verificare se un libro è digitale o cartaceo e stampare le informazioni del libro.
    Obiettivi Didattici: L’esercizio introduce il concetto di ereditarietà e polimorfismo, mostrando come gestire oggetti di tipo diverso in un contesto comune. Insegna anche come utilizzare metodi specifici di classi derivate.
  15. Associazione, Ereditarietà e Cast Dinamico – Paziente e Medico
    Si deve implementare una relazione di associazione tra una classe Paziente e una classe Medico, entrambe derivate da una classe base Persona. Il programma deve verificare che il medico associato sia effettivamente di tipo Medico.
    Obiettivi Didattici: L’esercizio combina associazione, ereditarietà e cast dinamico, mostrando come gestire relazioni complesse tra oggetti. Insegna anche come verificare il tipo di un oggetto in runtime.
  16. Strumenti musicali e costruttori in ereditarietà
    Si deve completare una classe Chitarra che eredita da una classe StrumentoMusicale. Il costruttore della chitarra deve chiamare correttamente quello della classe base e gestire un numero minimo di corde.
    Obiettivi Didattici: L’esercizio introduce il concetto di ereditarietà e costruttori in catena, mostrando come inizializzare attributi di classi derivate. Insegna anche come gestire vincoli sugli attributi.
  17. Gestione di figure geometriche
    Si deve completare una classe Rettangolo che eredita da una classe Figura e ridefinisce il metodo calcolaArea per calcolare l’area del rettangolo.
    Obiettivi Didattici: L’esercizio rafforza il concetto di ereditarietà e polimorfismo, mostrando come ridefinire metodi in classi derivate. Insegna anche come gestire calcoli specifici per ogni tipo di figura.
  18. Costruttori in catena di ereditarietà in Veicolo e Automobile
    Si deve completare una classe Automobile che eredita da una classe Veicolo. Il costruttore della classe derivata deve inizializzare correttamente gli attributi della classe base e quelli specifici della classe derivata.
    Obiettivi Didattici: L’esercizio introduce il concetto di costruttori in catena, mostrando come inizializzare attributi ereditati e specifici. Insegna anche come gestire l’ereditarietà in contesti di inizializzazione complessa.
  19. Costruttore di una classe derivata
    Si deve definire il costruttore di una classe derivata B che eredita da una classe base A. Il costruttore deve inizializzare correttamente gli attributi ereditati e quelli specifici della classe derivata.
    Obiettivi Didattici: L’esercizio rafforza il concetto di ereditarietà e costruttori, mostrando come gestire l’inizializzazione di attributi in classi derivate.
  20. Classe base per calcolare aree di figure diverse
    Si deve definire una classe base Figura e due classi derivate Quadrato e Triangolo che calcolano l’area rispettivamente.
    Obiettivi Didattici: L’esercizio introduce il concetto di ereditarietà e polimorfismo, mostrando come gestire calcoli specifici per ogni tipo di figura. Insegna anche come definire una classe base generica.
  21. Ereditarietà della classe NumeroPositivo
    Si deve implementare una classe Numeri che eredita da una classe NumeriPositivi e gestisce anche numeri negativi.
    Obiettivi Didattici: L’esercizio introduce il concetto di estensione di classi esistenti, mostrando come gestire nuovi requisiti in classi derivate. Insegna anche come gestire vincoli sugli attributi.
  22. Galline che fa l’uovo e cast di tipo
    Si deve implementare una classe Galline che eredita da una classe Animali e invoca un metodo specifico faiUovo solo se l’animale è una gallina.
    Obiettivi Didattici: L’esercizio combina ereditarietà e cast dinamico, mostrando come gestire metodi specifici di classi derivate. Insegna anche come verificare il tipo di un oggetto in runtime.