/* E' giunto il momento di sperimentare l'ereditarieta'.
 * Abbiamo una classe animale (superclasse), dalla quale possiamo derivare
 * sottoclassi di specie animali, ad esempio le specie giraffa e cervo.
 * Queste subclassi erediteranno le variabili lunghezza e numerozampe,
 * nonche' i metodi mettilungh(), mettizampe(), leggilungh() e leggizampe().
 * A queste variabili e metodi, comuni a tutti gli animali, aggiungeremo
 * manualmente le variabili e i metodi specifici della classe derivata.
 * In particolare, la classe derivata giraffa avra' in piu' una variabile
 * lungcollo e un paio di metodi pubblici, metticollo() e leggicollo(), in
 * modo da poter interfacciare tale variabile (privata) con l'esterno.
 * La classe derivata cervo, invece, avra' una variabile lungcorna e i
 * relativi metodi metticorna() e leggicorna().
 * Per derivare una classe da un'altra, si usa questa sintassi:
 *
 * class nome_nuova_classe : superclasse_ereditata {...};
 *
 * Ossia al nome si aggiunge il simbolo ":" seguito dalla superclasse padre
 * da cui si eredita il "patrimonio genetico" di metodi e variabili.
 * Ad esempio, dichiariamo la classe giraffa derivata da animale:
 *
 * class giraffa : animale {...};
 *
 * Si puo' anche specificare un identificatore di accesso, che noi metteremo
 * sempre public. Ecco quindi la classe figlia giraffa derivata da animale:
 *
 * class giraffa : public animale {
 *    float lungcollo;              // var. privata peculiare di giraffa
 * public:		            // La parte che segue e' PUBLIC
 *   void metticollo(float cl);     // Prototipi delle funzioni
 *   float leggicollo(void);        // peculiari di giraffa.
 * };
 *
 * A questo punto possiamo agevolmente definire i suoi metodi:
 *
 * void giraffa::metticollo(float cl)    // un metodo di giraffa
 * {
 *   lungcollo = cl;                  // accedo a una variabile di giraffa.
 * }
 *
 * A questo punto definire la subclasse cervo o altre non dovrebbe esservi
 * difficile.
 * Nel listato si potranno usare contemporaneamente istanze della
 * superclasse animale e delle due classi derivate.
 * Ricordo che la classe e' un tipo astratto usato per definire soltanto
 * l'organizzazione di variabili e istruzioni di un dato oggetto, e non
 * e' l'oggetto fisico utlilizzabile. Nel listato non si puo' pensare di
 * eseguire giraffa.leggicollo(). Bensi', si dovra' istanziare (ossia
 * creare fisicamente) un oggetto di tipo giraffa, cioe' un oggetto ( di
 * cui decidiamo il nome) la cui organizzazione interna e' stata definita
 * astrattamente nella classe giraffa: Il nome puo' essere Carlotta: a
 * questo punto avremo un esemplare, ossia un oggetto di quella classe,
 * chiamato Carlotta, e utilizzabile.
 * Ad esempio Fuffy e Buby sono istanze della razza (classe) cane.
 * La classe astratta "cane" non mangia, non beve, non abbaia, non si puo'
 * vedere, ne' toccare, ma solo pensare, in quanto e' un concetto teorico
 * che definisce e classifica un insieme di cose che effettivamente abbaiano,
 * e hanno nomi come Fuffy o Buby.
 * Queste classi sono organizzate in modo gerarchico, infatti se vediamo
 * una giraffa allo Zoo che si chiama Carlotta, vediamo un oggetto fisico,
 * istanziato, utilizzabile in un listato. Pero' riconosciamo che e' una
 * giraffa, e che le giraffe sono animali. Gli animali si possono distinguere
 * dalle piante per il fatto che hanno le zampe al posto delle radici e le
 * foglie, e le giraffe si possono distinguere dagli altri animali per il
 * collo lungo e il colore giallo a macchiette. Le giraffe inoltre hanno
 * in comune con i cervi l'appartenenza alla classe animale, e la non
 * appartenenza alla classe vegetale. Dunque si puo' ricostruire una
 * gerarchia simile alle diramazioni di un albero (genealogico, se si vuole),
 * che e' il modo piu' naturale per l'uomo di pensare e classificare le cose.
 * La programmazione ad oggetti infatti tende ad essere piu' vicina al modo
 * di pensare dell'uomo.
 * Si possono derivare da giraffa varie sottospecie di giraffe, ognuna delle
 * quali si potrebbe dividere nelle 2 classi maschio e femmina, e cosi' via.
 * Nel listato istanzieremo un esemplare della superclasse animale, che
 * chiameremo cane1 (consideriamolo un animale senza segni particolari),
 * e un esemplare per ognuna delle due subclassi, giraffa e cervo, che
 * chiameremo rispettivamente carlotta e carlone.
 * Sarebbe piu' logico derivare una subclasse cane da animale per definire
 * cane1, ma lo scopo del listato e' di dimostrare che si possono usare
 * contemporaneamente sia la classe "genitore" che le classi "figlie".
 * Anche in questo esempio definiamo variabili e oggetti dinamicamente
 * nel momento in cui servono.
 */

#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
    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 le funzioni (metodi) della classe animale:

/*-------------------------------------------------------------------------*
 * mettilungh: definisce la lunghezza dell'animale.
 *             parametri: in entrata la lunghezza in formato float.
 *-------------------------------------------------------------------------*/

void animale::mettilungh(float i)   // mettilungh() e' un metodo di animale
{
  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)   // mettizampe() e' un metodo di animale
{
  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)  // leggilungh() e' un metodo di animale
{
  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)  // leggizampe() e' un metodo di animale
{
  return numerozampe;
}

/***************************************************************************
 * Deriviamo due specie di animali particolari: giraffa e cervo.
 * Queste avranno da aggiungere al partimonio ereditato le caratteristiche
 * peculiari della propria specie: la lunghezza del collo la giraffa, e
 * e la lunghezza delle corna il cervo.
 * In seguito istanzieremo dei cervi e delle giraffe fisiche con un nome
 * proprio, ovvero istanzieremo degli oggetti di tipo giraffa e cervo.
 **************************************************************************/

// Iniziamo derivando la classe giraffa dalla superclasse animale.

class giraffa : public animale { // Classe giraffa derivata da animale.
    float lungcollo;             // PRIVATE - variabile peculiare di giraffa
 public:                         // La parte che segue e' PUBLIC
    void metticollo(float cl);   // Questi sono i prototipi delle funzioni
    float leggicollo(void);      // peculiari di giraffa.
 };

/*-------------------------------------------------------------------------*
 * metticollo: definisce la lunghezza del collo della giraffa
 *             parametri: in entrata la lungh. collo in formato float.
 *-------------------------------------------------------------------------*/

void giraffa::metticollo(float cl)  // metticollo() e' un metodo di giraffa
{
  lungcollo = cl;  // Scrive il valore nella variabile privata "leggicollo".
}

/*-------------------------------------------------------------------------*
 * leggicollo: legge e restituisce la lunghezza del collo della giraffa.
 *             parametri: in uscita la lunghezza del collo in formato float.
 *-------------------------------------------------------------------------*/

float giraffa::leggicollo(void)  // leggicollo() e' un metodo di giraffa
{
  return lungcollo;
}

/**************************************************************************/

// Ora deriviamo la classe cervo dalla superclasse animale.

class cervo : public animale {  // Classe cervo derivata da animale.
    float lungcorna;            // PRIVATE - variabile peculiare di cervo
 public:                        // La parte che segue e' PUBLIC
    void metticorna(float cn);  // Questi sono i prototipi delle funzioni
    float leggicorna(void);     // peculiari di cervo.
 };

/*-------------------------------------------------------------------------*
 * metticorna: definisce la lunghezza delle corna del cervo
 *             parametri: in entrata la lungh. corna in formato float.
 *             NB: non allude ne' ha a che vedere con le corna coniugali.
 *-------------------------------------------------------------------------*/

void cervo::metticorna(float cn)  // metticorna() e' un metodo di cervo
{
  lungcorna = cn;  // Scrive il valore nella variabile privata "leggicorna".
}

/*-------------------------------------------------------------------------*
 * leggicorna: legge e restituisce la lunghezza delle corna del cervo.
 *             parametri: in uscita la lungh. delle corna in formato float.
 *-------------------------------------------------------------------------*/

float cervo::leggicorna(void)  // leggicorna() e' un metodo di cervo
{
  return lungcorna;
}

///////////////////////////////////////////////////////////////////////////
//                            Il main...
///////////////////////////////////////////////////////////////////////////

int main(void)
{

  animale cane1;	// Istanzio un oggetto della classe animale

// Chiediamo all'utente le informazioni. Oggetto di tipo animale: cane1.

  cout << "\nNum. zampe cane 1? "; // Stampa la frase.
  int temp2;                       // Var. temporanea per il num. zampe.
  cin >> temp2;                    // Legge il valore.
  cane1.mettizampe(temp2);         // Passa a mettizampe la variabile temp2
  cout << "Lunghezza cane 1? ";    // Stampa la frase come un printf()
  float temp;                      // Var. temporanea per la lunghezza.
  cin >> temp;                     // Legge il valore come scanf()
  cane1.mettilungh(temp);          // Passa a mettilungh la variabile temp

// Ora l'oggetto di tipo giraffa: carlotta.

  giraffa carlotta;	            // Istanzio un oggetto di tipo giraffa
  cout << "Num. zampe carlotta? ";  // Stampa la frase come un printf()
  cin >> temp2;    		    // Legge il valore come scanf()
  cout << "Lunghezza carlotta? ";   // Stampa la frase come un printf()
  cin >> temp;                      // Legge il valore come scanf()
  carlotta.mettizampe(temp2);	    // Passa a mettizampe la variabile temp2
  carlotta.mettilungh(temp);        // Passa a mettilungh la la lunghezza.
  cout << "Lunghezza collo di carlotta? ";   // Stampa la frase.
  cin >> temp;                      // Legge il valore come scanf()
  carlotta.metticollo(temp);        // Passa a metticollo la variabile temp

// Infine l'oggetto di tipo cervo: carlone.

  cervo carlone;		    // Istanzio un oggetto di tipo cervo
  cout << "Num. zampe carlone? ";   // Stampa la frase come un printf()
  cin >> temp2;    		    // Legge il valore come scanf()
  cout << "Lunghezza carlone? ";    // Stampa la frase come un printf()
  cin >> temp;                      // Legge il valore come scanf()
  carlone.mettizampe(temp2);	    // Passa a mettizampe la variabile temp2
  carlone.mettilungh(temp);         // Passa a mettilungh la la lunghezza.
  cout << "Lunghezza corna di carlone? ";   // Stampa la frase.
  cin >> temp;                      // Legge il valore come scanf()
  carlone.metticorna(temp);         // Passa a metticorna la variabile temp

// Ora visualiziamo lo stato degli animali, usando i loro metodi di lettura.

  cout << "\nStato dell'animale cane1: zampe = " << cane1.leggizampe();
  cout << ", lunghezza = " << cane1.leggilungh();

  cout << "\nStato della giraffa carlotta: zampe = " << carlotta.leggizampe();
  cout << ", lunghezza = " << carlotta.leggilungh();
  cout << ", collo m. = " << carlotta.leggicollo();

  cout << "\nStato del cervo carlone: zampe = " << carlone.leggizampe();
  cout << ", lunghezza = " << carlone.leggilungh();
  cout << ", corna cm. = " << carlone.leggicorna();

  return 0;	// main() restituisce 0
}

/* Per derivare una classe, in Java al posto dei : si usa la parola "extends"
 * ad esempio la giraffa si deriva cosi':
 *
 * public class giraffa extends animale { ... }
 *
 * anziche':
 *
 * class giraffa : public animale { ... };
 *
 * In effetti quei due punti (:) si possono interpretare come "estende",
 * in quanto una classe derivata e' un'estensione della sua superclasse.
 */