• Non ci sono risultati.

PROGRAMMIAMOC++ - Costruttore e distruttore

N/A
N/A
Protected

Academic year: 2021

Condividi "PROGRAMMIAMOC++ - Costruttore e distruttore"

Copied!
7
0
0

Testo completo

(1)

Programma per la gestione di un conto corrente

Supponiamo ora di voler scrivere un programma a menu per la gestione di un conto corrente bancario. Possiamo dunque definire una classe conto così strutturata:

class conto { private:

double somma_depositata, //somma depositata sul conto tasso_interesse; // tasso di interesse annuo public:

void set_deposito(double); // assegna un valore alla somma depositata void set_tasso(double); // assegna un valore al tasso di interesse double get_deposito(); // legge il valore della somma presente sul conto double get_tasso(); // legge il valore del tasso di interesse

void versamento(double); // effettua il versamento di una somma sul conto int prelievo(double); // effettua un prelievo dal conto

void aggiornamento(); // aggiorna annualmente il deposito calcolando l'interesse };

I metodi della classe conto dovrebbero essere abbastanza esplicativi (lasciamo come utile esercizio al lettore la loro scrittura). Una sola precisazione è necessaria a proposito della funzione prelievo, la quale torna 1 se il prelievo è andato a buon fine (cioè se sul conto è presente la somma da prelevare), mentre torna 0 se non è stato possibile effettuare il prelievo (perché sul conto non è disponibile la somma richiesta).

Il programma principale, strutturato, come si è detto, a menu potrebbe essere il seguente:

int main(int argc, char *argv[]) {

conto cc;

int scelta;

double deposito, tasso, somma;

cout<<"Scegli l'operazione da effettuare:\n";

cout<<"1) assegna somma depositata\n2) assegna tasso di interesse\n";

cout<<"3) visualizza somma depositata\n4) visualizza tasso di interesse\n";

cout<<"5) effettua versamento\n6) effettua prelievo\n7) aggiorna conto\n";

cout<<"Scelta? ";

cin>> scelta;

switch (scelta) {

PROGRAMMIAMO

C++ - Costruttore e distruttore

C++ |Home |Contatti

(2)

case 1:

cout<<"Somma depositata: ";

cin>>deposito;

cc.set_deposito(deposito);

break;

case 2:

cout<<"Tasso di interesse: ";

cin>>tasso;

cc.set_tasso(tasso);

break;

case 3:

cout<<"Somma sul conto: "<<cc.get_deposito()<<"\n";

break;

case 4:

cout<<"Tasso di interesse: "<<cc.get_tasso()<<"\n";

break;

case 5:

cout<<"Somma da versare: ";

cin>>somma;

cc.versamento(somma);

break;

case 6:

cout<<"Somma da prelevare: ";

cin>>somma;

if (!cc.prelievo(somma))

cout<<"Errore: somma non disponibile sul conto.\n";

break;

case 7:

cc.aggiornamento();

cout<<"Aggiornamento annuale effettuato.\n";

break;

} }

Osserviamo che, affinché il programma funzioni correttamente, è necessario che, prima di eseguire qualsiasi altra operazione, venga depositata una somma iniziale sul conto (con set_deposito) e venga assegnato un valore al tasso di interesse (con set_interesse). In caso contrario le proprietà (i dati) somma_depositata e tasso_interesse non hanno alcun valore e i risultati di ogni altra operazione sono privi di senso.

Questo problema si verifica in C ogni qual volta si dichiara una variabile senza inizializzarla: il valore della variabile è indeterminato. Ciò può condurre potenzialmente a gravi errori, dei quali ci si accorge (talvolta) solo al momento dell'esecuzione del programma.

Costruttore di classe

Le classi prevedono in C++ uno strumento apposito per inizializzare le variabili della classe: il costruttore. Il costruttore (constructor) di una classe non è altro che un metodo speciale con le seguenti proprietà:

il costruttore ha sempre lo stesso nome della classe;

il costruttore è una funzione senza tipo, nemmeno il tipo "void";

il costruttore viene chiamato automaticamente ogni volta che viene dichiarato un oggetto appartenente a

(3)

quella certa classe.

Vediamo in pratica come potrebbe essere definito il costruttore della classe conto:

class conto { private:

double somma_depositata, //somma depositata sul conto tasso_interesse; // tasso di interesse annuo public:

conto() {

somma_depositata = 0;

tasso_interesse = 0;

}

void set_deposito(double); // assegna un valore alla somma depositata void set_tasso(double); // assegna un valore al tasso di interesse double get_deposito(); // legge il valore della somma presente sul conto double get_tasso(); // legge il valore del tasso di interesse

void versamento(double); // effettua il versamento di una somma sul conto int prelievo(double); // effettua un prelievo dal conto

void aggiorna_conto(); // aggiorna annualmente il deposito calcolando l'interesse };

Nell'esempio qui sopra il costruttore è stato definito all'interno della definizione della classe conto. Come per qualsiasi altra funzione, sarebbe stato anche possibile definirlo all'esterno della classe, lasciando nella classe il solo prototipo della funzione, in questo modo:

class conto { private:

double somma_depositata, //somma depositata sul conto tasso_interesse; // tasso di interesse annuo public:

conto() ;

void set_deposito(double); // assegna un valore alla somma depositata void set_tasso(double); // assegna un valore al tasso di interesse double get_deposito(); // legge il valore della somma presente sul conto double get_tasso(); // legge il valore del tasso di interesse

void versamento(double); // effettua il versamento di una somma sul conto int prelievo(double); // effettua un prelievo dal conto

void aggiorna_conto(); // aggiorna annualmente il deposito calcolando l'interesse };

conto::conto() // Si noti la ripetizione: il primo "conto" indica la classe, il secondo il costruttore {

somma_depositata = 0;

tasso_interesse = 0;

}

(4)

Il costruttore, a differenza degli altri metodi, non viene mai chiamato esplicitamente in un programma. Esso viene invece invocato automaticamente al momento della dichiarazione:

conto cc;

In questo modo non appena viene dichiarato l'oggetto cc, automaticamente vengono azzerate le sue proprietà somma_depositata e tasso_interesse. Si osservi che non sarebbe stato possibile inizializzare tali variabili all'interno della dichiarazione della classe conto, in questo modo:

class conto { private:

double somma_depositata=0, // ERRORE!

tasso_interesse=0; // Inizializzazioni non consentite!

....

D'altra parte non sarebbe neppure stato possibile inizializzare somma_depositata e tasso_interesse all'inizio del main, dal momento che si tratta di membri private della classe conto, che non possono essere usati dall'esterno.

Costruttore con parametri e overloading di costruttori

Il costruttore usato nell'esempio precedente è molto semplice, poiché prevede solo la possibilità che i dati vengano inizializzati a zero. Una definizione di costruttore più interessante potrebbe essere la seguente:

conto::conto(double som, double dep) {

somma_depositata = som;

tasso_interesse = dep;

}

Questo costruttore ha due parametri, som e dep, che servono per inizializzare con valori a piacere le proprietà della classe. Questo costruttore viene invocato al momento della dichiarazione di un oggetto di tipo conto in questo modo:

conto cc(12500 , 0.05); //inizializza somma_depositata a 12500 e tasso_interesse a 0.05 Vi è anche la possibilità di definire più costruttori per la stessa classe, in questo modo:

class conto { private:

double somma_depositata, //somma depositata sul conto tasso_interesse; // tasso di interesse annuo public:

conto() ;

conto(double, double);

void set_deposito(double); // assegna un valore alla somma depositata void set_tasso(double); // assegna un valore al tasso di interesse double get_deposito(); // legge il valore della somma presente sul conto double get_tasso(); // legge il valore del tasso di interesse

void versamento(double); // effettua il versamento di una somma sul conto

(5)

int prelievo(double); // effettua un prelievo dal conto

void aggiorna_conto(); // aggiorna annualmente il deposito calcolando l'interesse };

Si noti che in questo modo abbiamo due funzioni con lo stesso nome conto. In C++ è possibile definire due funzioni con lo stesso nome, purché esse differiscano per il numero e/o per il tipo dei parametri (non è invece possibile differenziare due funzioni con lo stesso nome in base al solo valore di ritorno). Il compilatore è in grado di stabilire in base alla chiamata a quale delle funzioni ci si sta riferendo. Questo meccanismo, su cui torneremo nel seguito, viene detto overloading di funzioni.

Nel nostro caso, se dichiariamo un oggetto in questo modo:

conto cc;

viene automaticamente invocato il costruttore senza parametri (quello che inizializza i valori a zero). Invece dichiarando l'oggetto così:

conto cc(12500 , 0.05);

viene invocato il costruttore con parametri.

Scrittura compatta di un costruttore

Il C++ consente anche di scrivere in modo più compatto il codice di un costruttore, come mette in evidenza il seguente confronto:

Scrittura estesa Scrittura compatta

conto::conto() {

somma_depositata = 0;

tasso_interesse = 0;

}

conto::conto() : somma_depositata(0), tasso_interesse(0) {}

conto::conto(double som, double dep)

{

somma_depositata = som;

tasso_interesse = dep;

}

conto::conto(double som, double dep) : somma_depositata(som), tasso_interesse(dep) {}

L'esempio seguente si riferisce al caso in cui il costruttore venga definito fuori dalla classe (lasciando nella classe solo il prototipo). Volendo invece dichiarare il costruttore all'interno della classe, la scrittura compatta è la

seguente:

class conto { private:

double somma_depositata, //somma depositata sul conto tasso_interesse; // tasso di interesse annuo public:

conto() : somma_depositata(0), tasso_interesse(0) {}

conto(double som, double dep) : somma_depositata(som), tasso_interesse(dep) {}

(6)

void set_deposito(double); // assegna un valore alla somma depositata void set_tasso(double); // assegna un valore al tasso di interesse double get_deposito(); // legge il valore della somma presente sul conto double get_tasso(); // legge il valore del tasso di interesse

void versamento(double); // effettua il versamento di una somma sul conto int prelievo(double); // effettua un prelievo dal conto

void aggiorna_conto(); // aggiorna annualmente il deposito calcolando l'interesse };

Distruttore

Il C++ permette di definire un altro metodo particolare con funzioni opposte a quelle del costruttore, detto

distruttore (destructor). Il distruttore ha lo stesso nome della classe a cui appartiene, preceduto però dal carattere

~ (detto tilde, combinazione di tasti ALT+126 sui PC Windows).

Il distruttore di una classe viene invocato automaticamente quando l'oggetto di appartenenza perde visibilità (di solito quando termina il programma) e la memoria occupata dai suoi attributi viene liberata. A differenza del costruttore, il distruttore non trova un largo impiego, tranne nelle classi che gestiscono la memoria dinamicamente:

in questi casi il distruttore consente di rilasciare lo spazio di memoria allocato per l'oggetto.

Il distruttore non può mai avere né argomenti né valore di ritorno. Per esempio nel caso della nostra classe conto potremmo aggiungere un distruttore ~conto() nel seguente modo:

class conto { private:

double somma_depositata, //somma depositata sul conto tasso_interesse; // tasso di interesse annuo public:

conto() ; //costruttore della classe senza parametri conto(double, double); // costruttore con parametri ~conto(); // distruttore

void set_deposito(double); // assegna un valore alla somma depositata void set_tasso(double); // assegna un valore al tasso di interesse double get_deposito(); // legge il valore della somma presente sul conto double get_tasso(); // legge il valore del tasso di interesse

void versamento(double); // effettua il versamento di una somma sul conto int prelievo(double); // effettua un prelievo dal conto

void aggiorna_conto(); // aggiorna annualmente il deposito calcolando l'interesse };

conto::~conto() {

cout<<"Oggetto eliminato\n";

}

Al termine dell'esecuzione del programma sul video compare il messaggio "Oggetto eliminato".

(7)

precedente - successiva Sito realizzato in base al template offerto da

http://www.graphixmania.it

Segui

Segui @ElePrograMania@ElePrograMania

Riferimenti

Documenti correlati

La gestione finanziaria, invece, ha assorbito un ammontare crescente di risorse soprattutto a seguito dell’incremento dell’indebitamento finanziario oneroso che, come visto

Bonifico all'estero in divisa estera spese dell'operazione 1,500 per mille con un minimo di euro 12,00 spese di registrazione euro 1,03 Per bonifici non STP (anche se in euro e

La voce comprende pertanto i proventi derivanti dall’attività di controllo e repressione delle irregolarità e degli illeciti (accertamenti al titolo 3 delle entrate:

Il FGD rimborserà i Suoi depositi (fino a 100.000 Euro) entro 7 giorni lavorativi decorrenti dalla data in cui si producono gli effetti del provvedimento di liquidazione

IMMOBILIZZAZIONI FINANZIARIE 9 di cui entro 12 mesi di cui entro 12 mesi

Il FGD rimborserà i Suoi depositi (fino a 100.000 euro) entro 7 giorni lavorativi decorrenti dalla data in cui si producono gli effetti del provvedimento di liquidazione

50/2016, DELLA MANIFESTAZIONE DI INTERESSE AD ESSERE INVITATI ALLA PROCEDURA NEGOZIATA PER L’AFFIDAMENTO DELL’INCARICO DI PROGETTAZIONE DEFINITIVA ED

56 DEL 10 MAGGIO 2018, PER L'AFFIDAMENTO DEI SERVIZI DI PROGETTAZIONE DEFINITIVA ED ESECUTIVA, COMPRESA RELAZIONE GEOLOGICA ED IL COORDINAMENTO DELLA SICUREZZA