appunti3s:introduzione_alle_classi
Differences
This shows you the differences between two versions of the page.
— | appunti3s:introduzione_alle_classi [2020/06/08 22:19] (current) – created - external edit 127.0.0.1 | ||
---|---|---|---|
Line 1: | Line 1: | ||
+ | ====== Le classi ====== | ||
+ | ===== Introduzione ===== | ||
+ | Anche gli oggetti, come le funzioni, sono pezzi di programma che possono essere riutilizzati, | ||
+ | Immaginando che il programma sia un insegnante che interroga gli studenti, e che come prima cosa debba conoscere il nome dello studente: | ||
+ | * Un insegnante //orientato alle funzioni//, prenderebbe in mano il documento dello studente, per poter leggere il nome dal suo documento. | ||
+ | * {{ : | ||
+ | * Un insegnante //orientato agli oggetti//, chiederebbe gentilmente allo studente di fornirgli il proprio nome. | ||
+ | * {{ : | ||
+ | |||
+ | Il primo insegnante, rispetto al secondo, agisce utilizzando un eccesso di forza e si comporta in modo sgarbato. Questo è il modo con cui si comporta una // | ||
+ | | ||
+ | |||
+ | Il secondo insegnante pensa che gli studenti abbiano diritto alla loro privacy e che inoltre sia più sicuro chiedere il nome invece che sperare di trovare, chissà in quale tasca, un documento. Anche il programmatore, | ||
+ | |||
+ | Ci sono anche altri vantaggi nell' | ||
+ | Per alcuni tipi di problemi la programmazione orientata agli oggetti invece non è la soluzione ideale.... | ||
+ | Di solito l' | ||
+ | Un po' come quando alcuni problemi si risolvono meglio usando la ricorsione e altri usando l' | ||
+ | ====Gli oggetti sono strumenti di lavoro==== | ||
+ | Gli oggetti sono strumenti che realizzano o forniscono qualcosa sui dati. | ||
+ | In questo modo si evita di occuparsi direttamente dei dati e si lascia che sia l' | ||
+ | ====Gli oggetti hanno una privacy==== | ||
+ | Gli oggetti sono responsabili dei propri dati, ma pretendono riservatezza. (vedere [[appunti3s: | ||
+ | |||
+ | ===== Esempio ===== | ||
+ | |||
+ | Le classi sono pezzi di codice che dipendono un po' anche da altri classi, ma come primo esempio si vedrà una sola classe. | ||
+ | Classe {{: | ||
+ | |||
+ | In particolare, | ||
+ | |||
+ | <file c contocorrente.h> | ||
+ | |||
+ | #include < | ||
+ | |||
+ | class ContoCorrente | ||
+ | { | ||
+ | | ||
+ | ContoCorrente(const float& cifra); | ||
+ | |||
+ | const float& saldo() const; | ||
+ | // poter modificare nemmeno tramite backdoor | ||
+ | void versareDenaro(const float& cifra); | ||
+ | void prelevareDenaro(const float& cifra); | ||
+ | |||
+ | | ||
+ | float mSaldo; | ||
+ | // potrebbe essere utile aggiungere | ||
+ | // il numero del conto | ||
+ | }; | ||
+ | |||
+ | </ | ||
+ | |||
+ | {{: | ||
+ | |||
+ | ==== Dati membro ==== | ||
+ | ... | ||
+ | ==== Funzioni membro ==== | ||
+ | |||
+ | All' | ||
+ | Il costruttore, | ||
+ | |||
+ | Le funzioni membro della classe ContoCorrente possono essere chiamate solo tramite un oggetto di tipo ContoCorrente, | ||
+ | Vedere anche codice sorgente di {{: | ||
+ | < | ||
+ | ContoCorrente mioConto(); | ||
+ | mioConto.preleva(30); | ||
+ | |||
+ | ==== Funzioni esterne ==== | ||
+ | |||
+ | Altre volte le funzioni potrebbero essere dichiarate anche fuori della classe, ma poi, per operare su un determinato oggetto, diventa necessario passare l' | ||
+ | |||
+ | |||
+ | < | ||
+ | void preleva(ContoCorrente& | ||
+ | // | ||
+ | < | ||
+ | |||
+ | ===== Incapsulamento delle funzioni===== | ||
+ | L' | ||
+ | ==== Data hiding ==== | ||
+ | Con //data hiding//, un caso particolare di incapsulamento, | ||
+ | ==== Specificatori di accesso ==== | ||
+ | Esistono tre // | ||
+ | * //public// | ||
+ | * // | ||
+ | * //private// | ||
+ | Lo specificatore di accesso è seguito da //due punti// (:) e modifica la visibilità di tutto quello che segue. | ||
+ | === public === | ||
+ | Quando un elemento viene dichiarato usando //public//, significa che vi si può accedere da qualsiasi parte. | ||
+ | === private === | ||
+ | Quando un elemento viene dichiarato usando // | ||
+ | === protected === | ||
+ | È usato nella composizione tra classi, come nell' | ||
+ | ==== Esempio ==== | ||
+ | |||
+ | Come nell' | ||
+ | |||
+ | ===== Costruttore ===== | ||
+ | Poiché la classe è un nuovo tipo di dato, esso deve descrivere, oltre alla struttura dei dati e delle sue funzioni membro, anche come (1)// | ||
+ | |||
+ | Il // | ||
+ | |||
+ | ====Dichiarazione==== | ||
+ | La // | ||
+ | - non restituisce nulla (neppure void); | ||
+ | - possiede lo stesso nome della classe a cui appartiene. | ||
+ | |||
+ | < | ||
+ | Class Esempio | ||
+ | { | ||
+ | public: | ||
+ | Esempio(); | ||
+ | // ma di dichiarare anche diversi costruttori personalizzati | ||
+ | // che differiscono solo per i parametri usati | ||
+ | Esempio(int a, int b); // dichiarazione del costruttore personalizzato | ||
+ | Esempio(const int a); | ||
+ | ~Esempio(); | ||
+ | int fun( int a); // dichiarazione di funzione membro | ||
+ | | ||
+ | private: | ||
+ | int x; | ||
+ | int y; | ||
+ | const int k; | ||
+ | Cosa c1; | ||
+ | Cosa& c2; | ||
+ | }; | ||
+ | </ | ||
+ | ====Definizione==== | ||
+ | Il costruttore costruisce l' | ||
+ | < | ||
+ | Esempio:: | ||
+ | { | ||
+ | x = a; // inizializzazione dei membri dell' | ||
+ | y = b; | ||
+ | // resto del codice... | ||
+ | } | ||
+ | </ | ||
+ | ===La lista di inizializzazione dei membri=== | ||
+ | C'è un modo molto comodo di mettere in evidenza l' | ||
+ | |||
+ | < | ||
+ | Esempio:: | ||
+ | : x(a), y(b) // inizializzazione tramite lista | ||
+ | { | ||
+ | // resto del codice... | ||
+ | } | ||
+ | |||
+ | </ | ||
+ | |||
+ | Questa tecnica, alternativa alle assegnazioni, | ||
+ | * per i membri costanti, | ||
+ | * per tutti i membri che non usano il costruttore predefinito (oggetti) | ||
+ | * per tutti i reference. | ||
+ | |||
+ | Prima verranno eseguiti tutti gli inizializzatori e dopo il codice definito nel costruttore | ||
+ | |||
+ | ===== Funzioni membro predefinite ===== | ||
+ | Sono funzioni che esistono sempre, anche se il programmatore non le definisce. In questo modo si ottiene la garanzia che alcune operazioni di uso frequente siano possibili. Si tratta di operazioni necessarie alla creazione/ | ||
+ | * costruttore minimo < | ||
+ | * distruttore | ||
+ | * costruttore di copia< | ||
+ | * operazione di assegnazione con copia < | ||
+ | |||
+ | Oltre ad essere operazioni frequenti, si tratta anche di operazioni delicate, e spesso il programmatore le deve ri-definire, | ||
+ | |||
+ | ==== Costruttore predefinito ==== | ||
+ | |||
+ | < | ||
+ | È utile definirlo quando si crea una nuova classe in una libreria, perché chi utilizzerà la libreria potrebbe creare un oggetto senza fornire adeguati elementi di inizializzazione ed un eventuale costruttore predefinito fornirebbe una certa garanzia sul contenuto del nuovo oggetto. | ||
+ | Inoltre il costruttore predefinito può essere riutilizzato all' | ||
+ | ==== Distruttore predefinito ==== | ||
+ | |||
+ | < | ||
+ | È molto simile al precedente, ma va ricordato che al distruttore non si passa (mai?) nessun argomento e quindi a maggior ragione è importante che esista sempre. | ||
+ | |||
+ | ==== Costruttore di copia predefinito ==== | ||
+ | Quando si vuole passare un oggetto ad una funzione __per valore__, il programma deve poter realizzare una copia di tale oggetto, perciò deve sapere come farlo. Questo costruttore dovrebbe essere personalizzato dal programmatore, | ||
+ | È bene comunque ricordare che in alternativa al passaggio per valore si potrebbe passare l' | ||
+ | |||
+ | Nel caso in cui un oggetto (x1) contiene puntatori ad altri oggetti (y1), il costruttore di copia predefinito effettuerebbe solo una copia dei suoi dati membro e verrebbero solo copiati gli indirizzi contenuti nei puntatori. | ||
+ | Esisterebbero due nuovi oggetti (x1 e x2), ma modificando il contenuto di x2 si rischia di modificare il contenuto di x1. | ||
+ | |||
+ | dichiarazione del costruttore con copia | ||
+ | < | ||
+ | |||
+ | definizione | ||
+ | < | ||
+ | :lista di inizializzazione.. | ||
+ | {}</ | ||
+ | |||
+ | ==== Operatore assegnazione di copia predefinito ==== | ||
+ | Quando si inizializza un oggetto (//a//) assegnandogli un altro oggetto dello stesso tipo (//b//), si esegue una copia di //b// su //a//. | ||
+ | < | ||
+ | Questa operazione di assegnazione opera in modo simile ad un costruttore di copia, dovendo inizializzare tutti i dati membro di a, in base a quelli di b. | ||
+ | |||
+ | dichiarazione dell' | ||
+ | < | ||
+ | |||
+ | definizione | ||
+ | < | ||
+ | { | ||
+ | //... | ||
+ | | ||
+ | }</ | ||
appunti3s/introduzione_alle_classi.txt · Last modified: 2020/06/08 22:19 by 127.0.0.1