Const, friend, static,this



Documenti analoghi
Inizializzazione, Assegnamento e Distruzione di Classi

Visibilità dei Membri di una Classe

costruttori e distruttori

Concetto di Funzione e Procedura METODI in Java

3 - Variabili. Programmazione e analisi di dati Modulo A: Programmazione in Java. Paolo Milazzo

void funzioneprova() { int x=2; cout<<"dentro la funzione x="<<x<<endl; }

Strutture. Strutture e Unioni. Definizione di strutture (2) Definizione di strutture (1)

Tipi primitivi. Ad esempio, il codice seguente dichiara una variabile di tipo intero, le assegna il valore 5 e stampa a schermo il suo contenuto:

Funzioni in C. Violetta Lonati

dall argomento argomento della malloc()

Allocazione dinamica della memoria - riepilogo

Java: Compilatore e Interprete

VARIABILI LOCALI E GLOBALI (ESTERNE)

Le funzioni in C. I programmi C sono costituiti da definizioni di variabili e funzioni.

Generalizzazione di funzioni e di classi. Macro come funzioni generiche

Oggetti Lezione 3. aspetti generali e definizione di classi I

Le operazioni di allocazione e deallocazione sono a carico del sistema.

Java:Struttura di Programma. Fabio Scanu a.s. 2014/2015


Laboratorio di programmazione

Eredità in C++ Corso di Linguaggi di Programmazione ad Oggetti 1. a cura di Giancarlo Cherchi

Corso di Informatica

La struttura dati ad albero binario

Università di Torino Facoltà di Scienze MFN Corso di Studi in Informatica. Programmazione I - corso B a.a prof.

Introduzione al linguaggio C Gli array

Università degli Studi di Cassino Corso di Fondamenti di Informatica Puntatori. Anno Accademico 2010/2011 Francesco Tortorella

Uso di JUnit. Fondamenti di informatica Oggetti e Java. JUnit. Luca Cabibbo. ottobre 2012

Fondamenti di Informatica e Laboratorio T-AB T-16 Progetti su più file. Funzioni come parametro. Parametri del main

I file di dati. Unità didattica D1 1

Test di unità con JUnit4

12 - Introduzione alla Programmazione Orientata agli Oggetti (Object Oriented Programming OOP)

GESTIONE INFORMATICA DEI DATI AZIENDALI

Programmazione a Oggetti Lezione 10. Ereditarieta

Variabili e tipi di dato

Modulo 4: Ereditarietà, interfacce e clonazione

La prima applicazione Java. Creazione di oggetti - 1. La prima applicazione Java: schema di esecuzione. Gianpaolo Cugola - Sistemi Informativi in Rete

Sottoprogrammi: astrazione procedurale

Le stringhe. Le stringhe

strutturare dati e codice

Codifica: dal diagramma a blocchi al linguaggio C++

Per scrivere una procedura che non deve restituire nessun valore e deve solo contenere le informazioni per le modalità delle porte e controlli

Dynamic Linking. Introduzione Creazione di una libreria dinamica Uso di una libreria dinamica

Linguaggio C - Stringhe

Esercizi della lezione 5 di Java

Programmazione in Java Parte I: Fondamenti

Esercizi sulla definizione di classi (Fondamenti di Informatica 1 Walter Didimo) Soluzioni

Gli array. Gli array. Gli array. Classi di memorizzazione per array. Inizializzazione esplicita degli array. Array e puntatori

I puntatori e l allocazione dinamica di memoria

Soluzione dell esercizio del 2 Febbraio 2004

Le variabili. Olga Scotti

Automatizzare i compiti ripetitivi. I file batch. File batch (1) File batch (2) Visualizzazione (2) Visualizzazione

Record in C: il costruttore struct.

Parola chiave extends

10 - Programmare con gli Array

Informatica 3. LEZIONE 7: Fondamenti di programmazione orientata agli oggetti (1)

Algebra di Boole: Concetti di base. Fondamenti di Informatica - D. Talia - UNICAL 1. Fondamenti di Informatica

Programmazione Java: Variabili membro, Metodi La parola chiave final

Programmazione Orientata agli Oggetti in Linguaggio Java

Funzioni. Il modello console. Interfaccia in modalità console

Programmazione a Oggetti Modulo B

INFORMATICA - I puntatori Roberta Gerboni

Corso di Laurea Ingegneria Informatica Fondamenti di Informatica

Corso di Informatica (Programmazione) Lezione 6 (31 ottobre 2008)

Arduino: Programmazione

Linguaggio C - Funzioni

Gestione dei File in C

Realizzazione di una classe con un associazione

Manuale Amministratore Legalmail Enterprise. Manuale ad uso degli Amministratori del Servizio Legalmail Enterprise

I casi d uso corrispondono ai compiti che l attore (che può essere una persona fisica e non) può svolgere.

obiettivi di questa seconda metà del corso fare un passo avanti rispetto a :... meccanismi di composizione dei dati

Introduzione a Classi e Oggetti

Quotazione compareto( ) Quotazione piurecente( ) Quotazione Quotazione Quotazione non trovato count( )

Risolvere un problema significa individuare un procedimento che permetta di arrivare al risultato partendo dai dati

Studente (Cognome Nome): Corso di Informatica Corso di Laurea in Ingegneria Gestionale a.a Secondo Compitino 21 Dicembre 2006

Esercitazione n 4. Obiettivi

GESTIONE DEI PROCESSI

Workland CRM. Workland CRM Rel /11/2013. Attività --> FIX. Magazzino --> NEW. Nessuna --> FIX. Ordini --> FIX

Introduzione. Java. Composizione. Esempio -- composizione. G. Prencipe È qualcosa che abbiamo già visto varie volte

Prossime lezioni. Dai TDA agli oggetti. Riassunto. Riassunto TDA. Oggi. Stefano Mizzaro 1

Excel. A cura di Luigi Labonia. luigi.lab@libero.it

20. Appunti sulle liste (gestione in linguaggio C#) 16/04/2015 Arraylist

Corso di Informatica Corso di Laurea in Ingegneria Gestionale a.a Secondo Compitino 17 Dicembre 2005

Sequence Diagram e Collaboration Diagram

Memory Management. Local Storage. Global Storage. Delete esplicite

Grammatica di base: Pointers

Utilizzo e scrittura di classi

Matematica - SMID : Programmazione Febbraio 2009 FOGLIO RISPOSTE

Come si può vedere, la regola è stata fatta in modo da spostare tutti i messaggi di Spam nella cartella del cestino.

Lezione 10: Librerie e compilazione separata

LA GESTIONE DELLE VISITE CLIENTI VIA WEB

Basi di dati. Il Linguaggio SQL. K. Donno - Il Linguaggio SQL

Laboratorio di Algoritmi e Strutture Dati

Corso di Laboratorio 2 Programmazione C++ Silvia Arcelli. 20 Ottobre 2014

Corso di Fondamenti di Informatica

Progettazione : Design Pattern Creazionali

Transcript:

Const, friend, static,this

Sommario Lo speficatore const per gli oggetti e le funzioni membro Le funzioni friend I membri static di una classe Il puntatore this

Oggetti const Alcuni oggetti devono poter essere modificati, altri no E possibile dichiarare un oggetto costante (immodificabile) con const Tempo mid(12,0); Ad es. l oggetto mid che rappresenta mezzogiorno può essere utilizzato come costante in operazioni di confronto Un oggetto costante può essere solo inizializzato Qualsiasi tentativo di modificare un oggetto const genera un errore in fase di compilazione

Oggetti const Utilizzare oggetti const è una buona norma di ingegneria del software (codice più sicuro) Utilizzare oggetti const migliora l efficienza: i compilatori riescono a ottimizzare il codice che opera su oggetti const

Dati membro const Anche i dati membro possono essere di tipo costante Un dato membro di una classe dichiarato come const non può essere usato a sinistra di operazioni di assegnamento Un dato membro const può solo essere inizializzato Un costruttore non può pertanto usare un operazione di assegnamento per attribuire un valore ad un dato const! class Data{ public: Data(int usr_dat=0){ dat=usr_dat; //ERRORE } const int dat; };

Dati membro const Come fare una inizializzazione in una classe? Un costruttore deve essere modificato nel seguente modo: class Data{ public: Data(int usr_dat=0):dat(usr_dat){} const int dat; }; La notazione :dat(usr_dat) inizializza dat con usr_dat NOTA: Non inizializzare un dato membro const è un errore

Dati membro const Se è necessario inizializzare più di una variabile lo si fa separando tramite virgole le varie inizializzazioni: class Data{ public: Data(int usr_dat1=0, int usr_dat2=0) :dat1(usr_dat1), dat2(usr_dat2){} const int dat1; const int dat2; };

Funzioni membro const Accedere alle funzioni membro per un oggetto dichiarato const potrebbe significare permettere che i dati membro (che devono rimanere costanti) siano alterati Il compilatore pertanto impedisce l accesso a funzioni membro const ma come utilizzare allora funzioni membro che (correttamente) non alterano i dati membro di un oggetto costante?

Funzioni membro const Non è possibile chiamare funzioni membro per oggetti const a meno che le funzioni non siano dichiarate const una funzione membro si dichiara const sia nel prototipo che nella definizione secondo la seguente sintassi: //nella dichiarazione di classe int restituisci_ora() const; //nella definizione int Tempo::restituisci_ora() const { return ora; }

Funzioni membro const E un errore se una funzione membro costante tenta di modificare un qualsiasi dato membro cioè: una funzione membro costante non può modificare dati membro di alcun tipo..ma internamente alla funzione possono essere dichiarate e modificate variabili locali int Tempo::restituisci_ora() const { int a; a=ora+2; return a; }

Funzioni membro const Non è possibile invocare funzioni const che a loro volto chiamino funzioni membro non-const una funzione const puo' usare solo altre funzioni const Non si deve dichiarare const un costruttore o distruttore! non e' di nessuna utilita' un costruttore o un distruttore che non puo' alterare i dati! Solo il costruttore di un oggetto costante può chiamare altre funzioni non costanti un costruttore ha una deroga speciale: lui lavora in un momento dell'esistenza dei dati simile alla inizializzazione e puo' pertanto usare ad es. funzioni set Nota: questo caso è differente dal inizializzare dei dati membro costanti; l'inizializzazione ha una sintassi speciale, in questo caso si usano funzioni nel corpo del costruttore

Esempio Class Dat{ public: Dat(int usr_dat=0){set(usr_dat);} void set(int usr_dat){dat=usr_dat;} void print()const{cout<<dat;} private: int dat; }; void main(){ const Dat my_dat(12); //OK my_dat.set(2); //ERROR my_dat.print();//ok }

Le funzioni friend Lo specificatore friend permette di definire funzioni al di fuori del campo di visibilità di una classe che possono accedere ai membri privati di tale classe Una classe B può essere dichiarata friend di una classe A in pratica tutti i dati membro e le funzioni membro private della classe A che concede l amicizia a B diventano accessibili per le funzioni membro di B in genere non si dichiarano classi friend ma si ricorre al concetto di ereditarietà (vedremo)

Le funzioni friend Dichiarazione: per dichiarare una funzione (classe) come friend di una classe basta precedere con la parola friend il prototipo della funzione (classe) nella dichiarazione della classe la definizione della funzione è di tipo usuale (non compare cioe' la parola friend)

A cosa servono le funzioni friend Quando non e' possibile modificare una classe Quando si vuole creare metodi comuni che operino su classi diverse Esempi di uso frequente: overloading di operatori iteratori

Esempio #include <iostream> class Count { friend void setx( Count &, int ); // friend declaration public: Count() { x = 0; } // constructor void print() const { cout << x << endl; } //output private: int x; // data member }; // Can modify private data of Count because // setx is declared as a friend function of Count void setx( Count &c, int val ){ c.x = val; // legal: setx is a friend of Count }

int main() { Count counter; } cout << "counter.x after instantiation: "; counter.print(); cout << "counter.x after call to setx friend function: "; setx( counter, 8 ); // set x with a friend counter.print(); return 0;

Le funzioni friend L amicizia è concessa non presa: all interno della classe si deve dichiarare esplicitamente quali funzioni sono considerate friend non è possibile dichiarare una funzione friend fuori da una dichiarazione di classe la dichiarazione friend non costituisce una dichiarazione della funzione, questa deve essere dichiarata nel modo ordinario Per accedere ad un membro di un oggetto la funzione deve ricevere l oggetto come parametro (in genere per riferimento)

Il puntatore this Ogni oggetto ha accesso al proprio indirizzo tramite il puntatore predefinito this: class Dat{ public: Dat(int a){x=a;} void print() const { cout<< x <<endl; cout<< this->x <<endl; cout<< (*this).x <<endl; } private: int x; }

Il puntatore this Un uso importante del puntatore this è di consentire la chiamata a cascata di funzioni membro Questo si realizza con una funzione membro che restituisce un alias a se stessa

Esempio class Tempo{ public: Tempo(int h=0, int m=0){set(h,m);} void set(int h, int m){seth(h);setm(m);} Tempo & seth(int h); Tempo & setm(int m); void print(){cout<<ora<< : <<min;} private: int ora, min; };

Tempo & Tempo::setH(int h){ ora=h; return *this; } Tempo & Tempo::setM(int m){ min=m; return *this; } void main{ } Tempo t(10,20); t.seth(11).setm(15); t.seth(2).print(); //OK t.print().setm(2); //ERROR

Spiegazione Ecco cosa accade quando viene eseguita l istruzione t.seth(11).setm(15); l operatore. associa da sinistra a destra (t.seth(11)).setm(15); viene creato un oggetto temporaneo senza nome per contenere il risultato restituito da t.seth(11) tale oggetto è un alias di t che adesso ha il dato membro ora modificato di tale oggetto (t) viene invocato il metodo t.setm(15); che nuovamente restituisce un oggetto temporaneo che è un alias di t

Ma quando un oggetto temporaneo viene distrutto non si invoca il distruttore? Quando l'alias temporaneo si distrugge non viene invocato alcun distruttore per la copia originale (si consideri il concetto di puntatore) Un alias è un puntatore (cambia solo la sintassi per riferirsi ad esso ed al dato puntato) pertanto quando viene deallocato si distrugge la variabile che conteneva l indirizzo dell oggetto solo quando si deve distruggere l oggetto si richiama il distruttore

Spiegazione Nel caso di t.print().setm(2); invece si ha: (t.print()).setm(2); ma t.print() restituisce un tipo void che non possiede alcuna funzione membro, tantomeno la funzione setm( )

Membri static di una classe Ogni oggetto possiede una copia dei dati membro della sua classe In alcuni casi si può volere che un dato sia condiviso da tutti gli oggetti appartenenti alla classe Per realizzare questo si dichiara il dato membro come static Un dato static e una specie di variabile globale ma con visibilità e accesso limitato agli oggetti di una unica specifica classe

Membri static di una classe Un membro static esiste anche quando non è stato ancora istanziato alcun oggetto della classe per accedervi: se il membro è public si usa: NomeClasse::nomeVariabile se il membro è private si devono usare le funzioni public (o friend) di un oggetto istanziato, oppure tramite una funzione membro static

Funzioni membro static Possono essere dichiarati static sia i dati membro che le funzioni membro Una funzione static può accedere solo ai membri static di una classe infatti si puo' chiamare una funzione static anche se non e' stato istanziato alcun oggetto e dunque quando ancora non esistono i dati membro

Esempio #ifndef EMPLOY1_H #define EMPLOY1_H class Employee { public: Employee( const char*, const char* ); // constructor ~Employee(); // destructor const char * getfirstname() const; // return first name const char * getlastname() const; // return last name static int getcount(); // return # objects instantiated private: char *firstname; char *lastname; // static data member static int count; // number of objects instantiated }; #endif

Esempio // Member function definitions for class Employee #include <iostream> #include <cstring> #include <cassert> #include "employ1.h" int Employee::count = 0; int Employee::getCount() { return count; } Employee::Employee( const char *first, const char *last ){ firstname = new char[ strlen( first ) + 1 ]; assert( firstname!= 0 ); // ensure memory allocated strcpy( firstname, first ); lastname = new char[ strlen( last ) + 1 ]; assert( lastname!= 0 ); // ensure memory allocated strcpy( lastname, last ); ++count; // increment static count of employees cout << "Employee constructor for " << firstname << ' ' << lastname << " called." << endl; }

Employee::~Employee() { cout << "~Employee() called for " << firstname << ' ' << lastname << endl; delete [] firstname; // recapture memory delete [] lastname; // recapture memory --count; // decrement static count of employees } const char * Employee::getFirstName() const{ // Const before return type prevents client from modifying // private data. Client should copy returned string before // destructor deletes storage to prevent undefined pointer return firstname; } const char * Employee::getLastName() const {return lastname;}

Esempio #include <iostream> #include "employ1.h" int main() { cout << "Number of employees before instantiation is " << Employee::getCount() << endl; // use class name Employee *e1ptr = new Employee( "Susan", "Baker" ); Employee *e2ptr = new Employee( "Robert", "Jones" ); cout << "Number of employees after instantiation is " << e1ptr->getcount(); cout << "\n\nemployee 1: " << e1ptr->getfirstname() << " " << e1ptr->getlastname() << "\nemployee 2: " << e2ptr->getfirstname() << " " << e2ptr->getlastname() << "\n\n";

delete e1ptr; // recapture memory e1ptr = 0; cout << "Number of employees after deletion is " << Employee::getCount() << endl; delete e2ptr; // recapture memory e2ptr = 0; cout << "Number of employees after deletion is " << Employee::getCount() << endl; } return 0;

Note La macro assert è definita in <cassert> assert(cond); verifica la condizione cond se è vera il programma continua se è falsa viene chiamata la funzione abort() che termina l esecuzione del programma e indica nel messaggio di errore la linea di codice in cui si è verificata la falsità di cond assert è utile in fase di debugging una volta terminata la fase di debugging basta aggiungere #define NDEBUG perché il preprocessore elimini il codice relativo a tutti gli utilizzi di assert