Lezione 12 – Appunti sulle classi in C++

9bc1a68eb59b0d8e0ec1bff5a930a956ee6653eb8a6c27a8cb2e8232d079a9c4Riguardando le varie lezioni di C++ ho notato che avevo dato per scontata una delle nozioni più importanti, ovvero la classe, a cui comunque avevo accennato nella precedente lezione ma nel solo contesto relativo alle basi di design grafico.

Una classe è uno strumento che da al programmatore la possibilità di definire nuovi type in più, come nel caso del design grafico, vi sono le classi derivate che invece permettono di organizzare templates e classi derivate che permettono al programmatore di usufruire delle loro relazioni.

La classe è un’entità astratta che si concretizza nel type. Per esempio, se sto programmando un videogame fantasy utilizzerò un type come Spell (Incantesimo). Ovviamente, nella scelta dei type si tenterà di creare dei comandi che siano in grado di rimandare ai concetti voluti rendendo più semplice sia la comprensione sia la modifica eventuale del programma.

Nella pratica il momento in cui un programmatore scrive una classe crea delle parti che andranno aggiunte all’interfaccia. Immaginiamoci, un programma complicato come può essere un videogioco, dove vogliamo creare un piccolo calendario che l’utente possa osservare: tutti i dati che ci servono non verranno inseriti nella stessa pagina ma, per comodità, verranno creati dei piani di lavoro. La classe si inserisce sul primo livello di lavoro, quello più basilare e, per questo, il nostro codice verrà salvato in una cartella chiamata, per esempio, interfaccia come file header ovvero .h. Questo, infatti, verrà poi utilizzato nel nostro codice di programmazione .cpp richiamandolo con un bel #include piazzato subito dopo il classico #include “iostream”.

Per applicare il concetto e definire la rappresentazione di un Date ed una serie di funzioni per manipolare le variabili possiamo usare una struttura (struct). Per esempio, osserviamo la costruzione del date prendendo l’esempio dal libro di Bjarne Stroustrup, Programming language.

struct Date {        //rappresentazione
       int d, m, y;
void init (int dd, int mm, int yy);   //inizializza d
void add_year (int n);    //aggiungi n anni a d
void add_month (int n);   //aggiungi n mesi a d
void add_day (int n);     //aggiungi n giorni a d
};

Il type void è un pointer che indica una memoria che viene, di norma, impiegato quando vogliamo trasmettere un address tra pezzi di codice che non conoscono il type l’uno dell’altro.

Lo stesso comando struct è per definizione una classe i cui membri sono predefiniti come pubblici, le funzioni ad esso connesse sono i suoi membri e possono essere richamati solo per una specifica variabile di un dato type. Diverse strutture, quindi, possono avere diversi membri con lo stesso nome, ecco perché lo specifichiamo quando definiamo tali membri di funzione.

Possiamo, quindi, anche sostituire struct Date { con il comando class Date {, questo ci permetterà di specificare che le funzioni date sono le uniche che dipenderanno dalla rappresentazione di Date e le uniche che daranno diretto accesso agli oggetti della classe Date. Inoltre, nello spazio lasciato libero tra int d,m,y; e void init possiamo aggiungere public: il quale ha la funzione di separare il corpo della classe in due parti. La prima parte potrà essere utilizzata solo dai membri della funzione mentre la seconda parte costituisce l’interfaccia pubblica degli oggetti della classe.

Probabilmente qualcuno si chiederà cos’è la funzione init ( ): essa viene utilizzata per avere una funzione che imposti il valore di un oggetto e renda i data privati forzandoci ad inserirli ma, normalmente, si predilige l’uso di un constructor il quale permette al programmatore di dichiarare una funzione che esplicitamente si proponga di inizializzare gli oggetti. Questi viene indicato con lo stesso nome della classe: sostituiremo, quindi, volendo init con Date.

Diamo un’occhiata ad alcune linee di comando (il codice è stato semplificato ma rende l’idea) per capire come scrivere, effettivamente, questo header.

//Header file .h
#ifndef DATE H        //include guard
#define DATE H
#include "iostream"
using namespace std;
class Date {
protected:
     date(const int& d, const int& m, const int& y);   //controlla la data e inizializza
public:
     Date(int d, int m, int y);    //anno, mese, giorno
     int day() const;   //valore non modificabile
     int month() const;
     int year() const;
     void set_day(const int& d);   //aggiungi giorno
     void set_month(const int& m); //aggiungi mese
     void set_year(const int& y);  //aggiungi giorno
};
#endif        //per #ifndef 

Nella prima sezione dedicata all’utilizzo delle librerie troviamo #ifndef che viene denominata Include guard oppure macro guard; questa macro serve per evitare problemi di doppia inclusione (per chi non lo sapesse la doppia inclusione fa parte dell’insiemistica: dati gli insiemi A e B troviamo che A=BAB e BA in cui il simbolo ⊆ significa incluso; quindi possiamo leggere il tutto in questo modo: “A è uguale a B se e solo se A è includo in B e B è incluso in A”). Facendo ciò rendiamo il nostro file.h indempotente ossia facciamo sì che non vi siano effetti collaterali (ovvero delle modificazioni di valori) nelle funzioni. Ogni qualvolta usiamo l’include guard dobbiamo necessariamente ricordarci di chiudere alla fine dei nostri comandi con #endif. Il codice tra #ifndef e #endif viene compilato solo se lo specifico identificatore è stato definito precedentemente: ecco perché troviamo nella seconda linea di comando delle librerie #define. Ormai, conosciamo già da tempo sia iostream che using namespace std per cui non mi ci soffermerò ma in caso di dubbi date un’occhiata qui.

Come già accennato class Date ci permette di specificare che le funzioni date sono le uniche a dipendere da Date e, successivamente, troveremo la suddivisione tra la parte privata (protected) e quella pubblica (public) relativamente all’interfaccia. Nella prima parte inseriremo i valori della variabile int, ovvero d, m, y (giorno-day, mese-month, anno-year) della classe Date.

Dopodiché troviamo l’uso dell’operatore & che altro non è che dire “si riferisce a” mentre il comando set imposterà la data. Mentre void è un return type di cui non ci interessa il risultato che la funzione restituisce.

Share the love

Comincia la discussione

Lascia un commento

Il tuo indirizzo email non sarà pubblicato.