/* Oltre ai metodi, possiamo sovrapporre (overload) anche i costruttori. * Supponiamo di voler rendere facoltativi i parametri del costruttore della * classe animale: * * class animale { // Definisco la classe animale * ... * public: // La parte che segue e' PUBLIC (visibile da tutti) * animale(void); // Costruttore: nessun parametro * animale(int zamp); // Costruttore: 1 par.: int zamp * animale(int zamp, float lungh); // Costruttore: 2 par.: zamp, lung * ~animale(void); // Distruttore * ... * }; * * // Ecco il costruttore senza parametri * * animale::animale(void) * { * lunghezza = 0; * numerozampe = 0; * } * * // Ecco il costruttore con 1 parametro: int zamp * * animale::animale(int zamp) * { * lunghezza = 0 * numerozampe = zamp; // Il num. zampe lo metto subito * } * * // Ecco il costruttore con 2 parametri: int zamp, float lung * * animale::animale(int zamp, float lung) * { * lunghezza = lung; * numerozampe = zamp; * } * * Ecco infine le possibili dichiarazioni: * * animale cane(); * animale cane(4); // Definisco subito che ha 4 zampe * animale cane(4,40.5) // Definisco subito 4 zampe e lungh. 40.5 cm * * Questo rende piu' flessibile l'inizializzazione del nostro oggetto. * Dato che questa e' solo una applicazione del polimorfismo ai costruttori, * niente di veramente nuovo, nel listato e' sfruttata una nuova possibilita' * permessa dal C++: la dichiarazione "al volo" di variabili all'interno di * un blocco, anziche' solo al suo inizio. Cio' e' illegale in C. * Un momento! Gli oggetti (classi), allora, non possono essere dichiarati * in un qualsiasi punto del listato, anziche' solo all'inizio? * Si! Basta chiamare i costruttori dove piu' ci pare.. o meglio al momento * che l'oggetto ci servira'. Questo permette di assegnare all'oggetto * (tramite il costruttore con parametri) dei valori che sappiamo solo in * un certo punto del listato, e non all'inizio. * Per esempio, possiamo creare l'oggetto animale quando sappiamo il numero * delle sue zampe, e non all'inizio, quando non lo sappiamo e non possiamo * fare altro che inizializzare tutto a zero, aspettando che il valore * venga immesso dal metodo mettizampe(). * In questo listato quindi "mixeremo" e inizializzeremo dinamicamente sia * le variabili che le classi, sfruttando la nuova liberta' permessa dal C++. */ #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 (visibile da tutti) animale(void); // Costruttore: nessun parametro animale(int zamp); // Costruttore: 1 par.: int zamp animale(int zamp, float lungh); // Costruttore: 2 par.: zamp, lung ~animale(void); // Distruttore void mettilungh(float i); // I prototipi dei metodi della void mettizampe(int l); // nostra classe. float leggilungh(void); int leggizampe(void); }; // Ora scriviamo le funzioni (metodi) della classe animale: // Ecco il costruttore senza parametri animale::animale(void) { lunghezza = 0; numerozampe = 0; } // Ecco il costruttore con 1 parametro: int zamp animale::animale(int zamp) { lunghezza = 0; numerozampe = zamp; // Il num. zampe lo metto subito } // Ecco il costruttore con 2 parametri: int zamp, float lung animale::animale(int zamp, float lung) { lunghezza = lung; numerozampe = zamp; } // 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) { // Da notare che iniziamo il programma senza aver dichiarato ne' classi, // ne' variabili!! Chiediamo all'utente di darci le informazioni. cout << "Num. zampe cane 1? "; // Stampa la frase. // Oooops! ci serve la variabile temp2! No prob., si puo' dichiarare ora. int temp2; // Variabile temporanea che usiamo per il num. zampe. Da // notare che la abbiamo definita dopo un'istruzione, e // non all'inizio. Questo e' illegale in C, ma legale in C++ cin >> temp2; // Legge il valore. // 2*Ooops! E l'oggetto? dichiariamone uno al volo, vah... animale cane1; // Istanzio cane1, senza passare parametri al costr. 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 // Veniamo al secondo oggetto. Le variabili temp e temp2 ormai ci sono gia'. // Qua comunque siamo piu' "furbi", perche' passiamo direttamente al // costruttore il num. di zampe, evitando di chiamare mettizampe(). cout << "Num. zampe cane 2? "; // Stampa la frase come un printf() cin >> temp2; // Legge il valore come scanf() cout << "Lunghezza cane 2? "; // Stampa la frase come un printf() cin >> temp; // Legge il valore come scanf() animale cane2(temp2); // Istanzio cane2, passando al cost. il num. zampe cane2.mettilungh(temp); // Passa a mettilungh la la lunghezza. // Il millepiedi lo definiamo in un sol colpo usando il costruttore con 2 // parametri, definito prima sovrapponendolo (overload) agli altri 2. animale millepiedi(1000,3); // Istanzio millepiedi, passando il num. // zampe e la lunghezza al costruttore. // 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 } /* A questo punto si potrebbero "overloadare" anche i metodi, permettendo * di inserire altri dati, facoltativamente... se volete fatelo voi. * Per quanto riguarda la nuova dichiarazione delle variabili, possibile * anche nel punto del listato dove sono utilizzate, e' evidente lo spirito * Object Oriented dell'incapsulation di codice e' dati. * Inoltre cio' rende possibile l'inizializzazione dinamica, ossia e' * possibile assegnare alla variabile che si crea il risultato di una * espressione calcolata precedentemente, magari diversa ogni volta: * * cout << "Lunghezza di 2 Pippi? "; // Stampa la frase come un printf() * cin >> temp; // Legge il valore come scanf() * int pippo = temp/2; // Creo un int e lo inizializzo dinamicamente * * La variabile pippo e' creata e inizializzata con un valore diverso per * ogni esecuzione del programma (dipende da cosa scrive l'utente). * Lo stesso vale per i costruttori parametrici delle classi. */