/* 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.
*/
