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