1 FONDAMENTI DI INFORMATICA II Ingegneria Gestionale a.a ° Ciclo Strutture e Classi
2 Strutture Definizione di struttura: Una struttura è un tipo di dato costituito da un aggregato di dati di altri tipi, detti dati membro della struttura. La definizione di struttura non riserva quindi spazio in memoria. La definizione di una struttura si ottiene nel seguente modo: struct Nome_Struttura { Tipo_Membro_1 Nome_Membro_1; Tipo_Membro_2 Nome_Membro_2; ………….}; Esempio: struct tipoStruct { int numCode; float dataInfo; };
3 Strutture Dati membro di una struttura: I dati membro di una struttura possono essere di qualsiasi tipo ad eccezione di istanze di se stessa. Tra i dati membro di una struttura possono essere inclusi i puntatori alla struttura stessa (strutture autoreferenti). Esempio: struct tipoStruct { int numCode; float dataInfo; tipoStruct *tipoPtr; };
4 Strutture Dichiarazione di una struttura: I tipi di dato definiti come strutture possono essere utilizzati per dichiarare variabili, seguendo le regole classiche della dichiarazione delle variabili: in tal caso ogni variabile così dichiarata ha la composizione della struttura. Possibili dichiarazioni sono: Nome_Struttura Nome_Variabile_Struttura, Nome_Array_di_Strutture [Dimensione_Array], *Nome_Puntatore_a_Struttura, &Nome_Alias_Struttura= Nome_Variabile_Struttura; Esempio: tipoStruct varStruct, arrayStruct[10], *structPtr, &aliasVar=varStruct;
5 Strutture Accesso ai membri di una struttura: Con l’operatore punto: …...Nome_Variabile_Struttura. Nome_Membro Con l’alias e l’operatore punto: …...Nome_Alias_Struttura. Nome_Membro Con il puntatore e l’operatore freccia: Nome_Puntatore_a_Struttura= &Nome_Variabile_Struttura; …..Nome_Puntatore_a_Struttura ->Nome_Membro Con il puntatore e l’operatore punto: …..(* Nome_Puntatore_a_Struttura ). Nome_Membro
6 Strutture Esempi di accesso ai membri di una struttura: struct tipoStruct { int numCode; float dataInfo; }; tipoStruct varStruct, arrayStruct[10], *structPtr, &aliasVar=varStruct; intvarInt; float varFloat= 10.5; varStruct. numCode= 10; varInt= aliasVar.numCode; varStruct. dataInfo= varFloat; arrayStruct [5]. numCode= varInt; structPtr= &varStruct; varInt= structPtr -> numCode; varInt= (*structPtr).numCode;
7 Classi Definizione di classe: Una classe è un tipo di dato costituito da un aggregato di dati di altri tipi e da funzioni, detti rispettivamente dati e funzioni membro. Una classe può rappresentare un insieme di oggetti che hanno certi attributi (dati membro) e certi comportamenti (funzioni membro). La definizione di una classe si ottiene nel seguente modo: class Nome_Classe { public: Nome_Classe ( );//Costruttore // Seguono le implementazioni o i prototipi delle funzioni //e le dichiarazioni dei dati di accesso pubblico ………………………. private: // Seguono le implementazioni o i prototipi delle funzioni //e le dichiarazioni dei dati di accesso privato ………………………. };
8 Classi Esempio: class Clock { public: Clock ( );//Costruttore void setTime (int, int, int); void displayTime ( ); void incTime ( ); private: int ora, minuti, secondi; }; Accesso Pubblico: Le funzioni e i dati definiti con accesso pubblico possono essere acceduti anche dal codice che non fa parte della classe (esterno) Accesso Privato: Le funzioni e i dati definiti con accesso privato possono essere acceduti solo (con qualche eccezione) dalle funzioni membro della classe
9 Classi Dichiarazione di una variabile classe: I tipi di dato definiti con le classi possono essere utilizzati per dichiarare variabili, seguendo le regole classiche della dichiarazione delle variabili.Una variabile dichiarata utilizzando il tipo definito da una classe prende il nome di “instanziazione” o “oggetto” di quella classe. Possibili dichiarazioni sono: Nome_Classe Nome_Oggetto, Nome_Array_di_Oggetti [Dimensione_Array], *Nome_Puntatore_a_Oggetto, &Nome_Alias_Oggetto= Nome_Oggetto; Esempi di instanziazioni di classe: Clock rolex, arrayClock[10], *rolexPtr, &aliasClock=rolex;
10 Classi Costruttore della classe: E’ una funzione membro che ha lo stesso nome della classe, non restituisce alcun tipo di dato ed ha il compito di inizializzare i dati membro della classe quando viene dichiarata una variabile del tipo della classe. Il prototipo del costruttore nella definizione di una classe può avere degli argomenti, normalmente dichiarati con una lista di tipi di variabili. A questi argomenti possono essere assegnati dei valori di default facendo seguire al tipo di variabile l’assegnazione nel seguente modo: …, Tipo_Variabile = Valore_di_Default, …… Comunque agli argomenti, anche se esistono dei valori di default, possono essere assegnati i valori al momento dell’instanziazione dell’oggetto della classe facendo seguire, al nome dell’oggetto instanziato, la lista dei valori degli argomenti racchiusa tra parentesi tonde. Se la lista dei valori è incompleta, deve esserci un’assegnazione di default per gli ultimi argomenti.
11 Classi Esempio: class Clock { public: Clock (int=0, int=0, int=0);//Costruttore void setTime (int, int, int); void displayTime ( ); void incTime ( ); private: int ora, minuti, secondi; }; …………………………………….. Clock rolex, vetta (5, 3), bulova (5, 3, 2); …………………………………….
12 Classi Distruttore della classe: E’ una funzione che ha lo stesso nome della classe preceduto da tilde (~). Un distruttore è quindi come segue: ~ Nome_Classe ( ); Il distruttore non accetta argomenti in input e non restituisce dati. Il distruttore effettua le funzioni finali prima che la memoria di un oggetto sia restituita al sistema. Se non c’è un distruttore esplicito il sistema ne crea uno di default. Il distruttore viene richiamato quando il programma supera lo scope entro cui è definito l’oggetto, a meno che l’oggetto non sia stato dichiarato static, nel qual caso viene richiamato solo a fine programma main o quando viene chiamata la funzione exit.
13 Classi Implementazione delle funzioni membro: Le funzioni membro possono avere la loro implementazione all’interno della definizione della classe (considerata come blocco). In questo caso diventano automaticamente inline, ossia il loro codice viene ripetuto tutte le volte che vengono invocate. Le funzioni membro che hanno il prototipo nella definizione di classe e l’implementazione all’esterno, devono utilizzare l’operatore binario di risoluzione dello scope (::). Questo operatore deve essere preceduto dal nome della classe e deve essere seguito dal nome della funzione, ossia: Tipo_Restituito/Void Nome_Classe :: Nome_Funzione (……) {……//Codice di implementazione della funzione }
14 Classi Esempio: class Clock { public: Clock (int=0, int=0, int=0);//Costruttore void setTime (int, int, int); void displayTime ( ); void incTime ( ); private: int ora, minuti, secondi; }; void Clock :: setTime (int a, int b, int c) {ora= a; minuti= b; secondi= c;} …………………………………….. Clock rolex, vetta (5, 3), bulova (5, 3, 2); …………………………………….
15 Classi Accesso ai membri di una classe: I dati e le funzioni membro (interne o esterne alla definizione) di una classe appartengono quindi allo scope di tale classe. Tutti i membri di una classe sono perciò immediatamente accessibili a tutte le funzioni membro della classe e possono essere riferiti semplicemente con il proprio nome. L’accesso ai membri (pubblici) di una classe dall’esterno dello scope di classe (ad es. dal main) si ottiene, una volta che è stato instanziato un oggetto di quella classe, con gli stessi operatori (. e ->) già descritti per le strutture e il nome, il riferimento o il puntatore dell’oggetto (handle dell’oggetto).
16 Classi Accesso (esterno allo scope) ai membri di una classe: Con l’operatore punto: …...Nome_Oggetto. Nome_Membro Con l’alias e l’operatore punto: …...Nome_Alias_Oggetto. Nome_Membro Con il puntatore e l’operatore freccia: Nome_Puntatore_a_Oggetto= &Nome_Oggetto; …..Nome_Puntatore_a_Oggetto ->Nome_Membro Con il puntatore e l’operatore punto: …..(* Nome_Puntatore_a_Oggetto ). Nome_Membro
17 Classi Esempio: class Clock { public: Clock (int=0, int=0, int=0);//Costruttore void setTime (int, int, int); void displayTime ( ); void incTime ( ); int giorno, mese, anno; private: int ora, minuti, secondi; }; Clock :: Clock (int k, int j, int x) {setTime (k, j, x);} ………. Clock vetta(12, 15, 10), *vediPtr, &copia=vetta; vediPtr= &vetta; int o= vetta.giorno; int m= copia.mese; int s= vediPtr ->anno; s= (*vediPtr). anno;
18 Classi Esempio: class Clock { public: Clock (int=0, int=0, int=0);//Costruttore void setTime (int, int, int); void displayTime ( ); void incTime ( ); int giorno, mese, anno; private: int ora, minuti, secondi; }; Clock :: Clock (int k, int j, int x) {setTime (k, j, x);} ………. Clock vetta(12, 15, 10), *vediPtr, &copia=vetta; vediPtr= &vetta; vetta.incTime ( ); vediPtr-> displayTime ( ); (*vediPtr).incTime( );
19 Classi Ancora sulle funzioni membro Le funzioni membro di una classe possono essere sovrascritte, ma solo da altre funzioni membro della stessa classe. Le funzioni membro hanno scope di funzione in una classe, quindi le variabili definite al loro interno sono note solo alle rispettive funzioni. Se all’interno di una funzione membro è definita una variabile con lo stesso nome di una variabile con scope di classe quest’ultima è normalmente mascherata e può essere acceduta dall’interno della funzione solo con l’operatore binario di risoluzione dello scope (Nome_Classe :: Nome_Variabile). L’operatore unario di risoluzione dello scope serve inoltre ad accedere alle variabili globali.
20 Classi Separazione di interfaccia ed implementazione: #ifndef FILEINTESTAZ_H #define FILEINTESTAZ_H ….Definizioni delle classi con prototipi delle funzioni membro……….. #endif FileIntestaz.h Impediscono doppie inclusioni Crea il file di intestazioni #include “FileIntestaz.h …Implementazione delle funzioni membro ……. FileFunzioni.cpp #include…… #include “FileIntestaz.h ……. int main ( ) {..instanziazione oggetti e accessi ai suoi membri..} FileClient.cpp
21 Classi Caso di funzione membro che restituisce un riferimento: Il riferimento restituito da una funzione membro può essere relativo ad una qualsiasi delle variabili normalmente accedute dalla funzione, ossia anche relativo ai dati membro della classe. L’utilizzo del riferimento restituito consente di accedere ai dati membro anche dall’esterno della funzione (ad es. dal main) e quindi di alterare in modo non corretto (ma consentito!) anche i dati membro privati. Assegnazione tra oggetti: L’operatore di assegnazione = tra due oggetti (della stessa classe!) comporta la copia membro a membro. Un oggetto può essere passato come argomento di una funzione ed essere ricevuto in restituzione. Questo si può ottenere per valore, per riferimento tramite un puntatore o per riferimento tramite un riferimento.