/* Spesso prima di usare una classe occorre inizializzarla, ad esempio * puo' servire di azzerare certe variabili, o allocare della memoria. * Allo stesso modo, quando la classe non serve piu', puo' dover essere * eseguita qualche operazione di deallocazione della memoria o simili. * Cio' si puo' fare aggiungendo 2 metodi pubblici, che dovranno essere * chiamati (ovvero dovranno ricevere messaggi) all'inizio e alla fine * del programma: * * class animale { // Definisco la classe animale * ... // Questa parte e' PRIVATE di default * public: // La parte che segue e' PUBLIC * void inizializ(void); // Questi sono i prototipi delle funzioni * void distruggi(void); // (o metodi) della nostra classe. * ... * }; * * Nel main() dovremo chiamare inizializ() all'inizio e distruggi() alla * fine, prima di uscire: * * animale cane1,cane2,millepiedi; // Ecco che istanzio 3 animali... * * cane1.inizializ(); // Chiamiamo il metodo inizializ() di cane1 * cane2.inizializ(); // e quello di cane2, nonche'... * millepiedi.inizializ(); // quello di millepiedi. * * ... // Qua lo svolgimento del programma * * cane1.distruggi(); // Chiamiamo il metodo distruggi() di cane1 * cane2.distruggi(); // e quello di cane2, nonche'... * millepiedi.distruggi(); // quello di millepiedi. * * return 0; // Uscita dal programma * * Come si vede, ci sono 2 inconvenienti: uno e' quello di doversi ricordare * sia all'inizio che alla fine di chiamare i metodi, e l'altro e' quello * del dover ripetere l'operazione per tutti gli oggetti, che possono essere * anche decine. * Di conseguenza sono stati implementati dei costruttori e dei distruttori * "automatici", che vengono chiamati alla dichiarazione dell'oggetto e * alla fine del suo utilizzo, senza dover intervenire, e senza che ce ne * accorgiamo, a meno che non stampino messaggi. * Il costruttore e' un metodo che ha lo stesso nome della classe, ad es: * * animale(void); // Costruttore * * Da notare che il costruttore non puo' restituire alcun valore, per cui * non si fa precedere dal tipo di restituzione. * Il distruttore ha lo stesso nome del costruttore, ma e' preceduto da un * carattere tilde ~ che sulle tastiere italiane non e' presente, per cui * si puo' ottenere con ALT+126 (su sistemi msdos). * * ~animale(void); // Distruttore * * Vediamo ora la nostra classe munita di costruttore e distruttore: * * class animale { // Definisco la classe animale * float lunghezza; // Questa parte e' PRIVATE di default * int numerozampe; * public: // La parte che segue e' PUBLIC (visibile da tutti) * animale(void); // Costruttore * ~animale(void); // Distruttore * void mettilungh(float i); // Questi sono i prototipi dei metodi * void mettizampe(int l); // della nostra classe. * float leggilungh(void); * int leggizampe(void); * }; * * // Ecco il costruttore * * animale::animale(void) * { * lunghezza = 0; * numerozampe = 0; * cout << "animale inizializzato\n"; * } * * // Ecco il distruttore * * animale::~animale(void) * { * cout << "animale distrutto\n"; * } * * Nel nostro esempio stampiamo delle stringhe, ma questo solo per rendere * visibile l'esecuzione dei distruttori e dei costruttori. * Raramente stamperemo inutili messaggi come questi, nella pratica. */ #include <iostream.h> // Header necessario per usare CIN e COUT // Questo e' un commento C++ ad una sola linea class animale { // Definisco la classe animale float lunghezza; // Questa parte e' PRIVATE di default int numerozampe; public: // La parte che segue e' PUBLIC animale(void); // Costruttore ~animale(void); // Distruttore void mettilungh(float i); // Questi sono i prototipi delle funzioni void mettizampe(int l); // (o metodi) della nostra classe. float leggilungh(void); int leggizampe(void); }; // Ora scriviamo o metodi della classe animale: // Ecco il costruttore animale::animale(void) { lunghezza = 0; numerozampe = 0; cout << "animale inizializzato\n"; } // Ecco il distruttore animale::~animale(void) { cout << "animale distrutto\n"; } /*-------------------------------------------------------------------------* * mettilungh: definisce la lunghezza dell'animale. * parametri: in entrata la lunghezza in formato float. *-------------------------------------------------------------------------*/ void animale::mettilungh(float i) { lunghezza = i; // Scrive il valore nella variabile privata "lunghezza". } /*-------------------------------------------------------------------------* * mettizampe: definisce il numero di zampe dell'animale. * parametri: in entrata il num. di zampe in formato int. *-------------------------------------------------------------------------*/ void animale::mettizampe(int l) { numerozampe = l; // Scrive il valore nella variabile privata "numerozampe". } /*-------------------------------------------------------------------------* * leggilungh: legge e restituisce la lunghezza dell'animale. * parametri: in uscita la lunghezza in formato float. *-------------------------------------------------------------------------*/ float animale::leggilungh(void) { return lunghezza; } /*-------------------------------------------------------------------------* * leggizampe: legge e restituisce il num. di zampe dell'animale. * parametri: in uscita il num. di zampe in formato int. *-------------------------------------------------------------------------*/ int animale::leggizampe(void) { return numerozampe; } /////////////////////////////////////////////////////////////////////////// // Il main... /////////////////////////////////////////////////////////////////////////// int main(void) { float temp; // Variabile temporanea che usiamo per le lunghezze. int temp2; // Idem, per il num. zampe. // Ora possiamo dichiarare alcuni oggetti di tipo animale e usarli: animale cane1,cane2,millepiedi; // ecco che istanzio 3 animali... // ossia creo degli esemplari dalla // stessa classe "astratta". // Non possiamo accedere direttamente ai dati come abbiamo fatto prima, // con cane1.numerozampe = 4; eccetera. Ora dobbiamo mandare un messaggio // all'oggetto chiedendogli di modificare la sua variabile. cane1.mettizampe(4); // Chiamiamo il metodo mettizampe() di cane1 cane2.mettizampe(4); // e quello di cane2, per variare le loro millepiedi.mettizampe(1000); // variabili private. Stesso per millepiedi // Gli altri parametri li chiediamo all'utente. cout << "\nLunghezza cane 1? "; // Stampa la frase come un printf() cin >> temp; // Legge il valore come scanf() cane1.mettilungh(temp); // Passa a mettilungh la variabile temp cout << "Lunghezza cane 2? "; // Stampa la frase come un printf() cin >> temp; // Legge il valore come scanf() cane2.mettilungh(temp); // Passa a mettilungh la variabile temp cout << "Lunghezza millepiedi? "; // Stampa la frase come un printf() cin >> temp; // Legge il valore come scanf() millepiedi.mettilungh(temp); // Passa a mettilungh la variabile temp cout << "Num. esatto piedi del millepiedi? "; // Stampa la frase. cin >> temp2; // Legge il valore. millepiedi.mettizampe(temp2); // Passa a mettizampe la variabile temp2 // Ora visualiziamo lo stato degli animali, usando i loro metodi di lettura. cout << "\nStato del cane1: zampe = " << cane1.leggizampe(); cout << ", lunghezza = " << cane1.leggilungh(); cout << "\nStato del cane2: zampe = " << cane2.leggizampe(); cout << ", lunghezza = " << cane2.leggilungh(); cout << "\nStato del millepiedi: zampe = " << millepiedi.leggizampe(); cout << ", lunghezza = " << millepiedi.leggilungh() << "\n"; return 0; // main() restituisce 0 } /* La differenza in output con il listato precedente, e' che prima della * domanda "Lunghezza cane 1?" viene stampato: * * animale inizializzato * animale inizializzato * animale inizializzato * * Mentre dopo l'ultima risposta (lunghezza del millepiedi), prima * dell'uscita, si nota: * * animale distrutto * animale distrutto * animale distrutto * * Questo evidenzia il momento in cui sono chiamati i costruttori e i * distruttori dei 3 oggetti. */