Guida CPP
Guida CPP
<1>
Guida C++
Aspetti Avanzati
#Name: Guida C++: Aspetti Avanzati #Author: Giuseppe_N3mes1s #Licence: GNU/GPL # !"ai#: dottor$e%i##_mister&tisca#i'it #(eve#opment: 3)/1*/*))+
./Giuseppe_N3mes1s
<2>
Con ,uesta Guida vorrei apportare #e mie conoscenze su# C++ ad a#tri utenti- rendendomi partecipe di aumentare un po #a conoscenza su ,uesto Lin.ua..io di pro.rammazione' La .uida presuppone che #/utente a00ia .ia/ una discreta se non ottima preparazione 0asi#are su##/aro.omento- in ,uanto- #a codesta non parte da come si crea un 1he##o 2or#d34ma i# suo percorso inizia da- su cose/ #a pro.rammazione modu#are in C++- 5ino ad arrivare a##e 6trutture dati Astratte' 7# tutto e/ composto da .uide scritte da me- prendendo spunto da testi universitari' (opo aver 5atto ,uesta semp#ice premessa possiamo iniziare con #/indice de.#i ar.omenti e poi passeremo ad appro5ondire o.nuno di essi' 6a#uti e 8uon Prose.uimento di 6tudio
Giuseppe_N3mes1s
./Giuseppe_N3mes1s
<3>
Pro.rammazione "odu#are in C++9 La ;icorsione9 <unzioni Aspetti Avanzati9 7ntroduzione a##a Pro.rammazione ad >..etti ed i# C++9 reditariet@9 Po#imor5ismo9 Le C#assi: notazioni di 0ase de# C++9 Puntatori9 C#assi di memorizzazioni de##e varia0i#i in C++9 Conversione di tipo Bcastin.C in C++9 ;ide5inizione de.#i operatori9 7# 6istema di 7/> in C++9 6trutture (ati Astratte'
pa. '/: pa. '/13 pa. '/1= pa. '/1? pa. '/*: pa. '/3A pa. '/3+ pa. '/A= pa. '/:) pa. '/:: pa. '/:D pa. '/== pa. '/D:
Conc#usioni
pa. '/D?
./Giuseppe_N3mes1s
<4>
./Giuseppe_N3mes1s
<5>
#/uso di 0i0#ioteche di 5unzioni .ia/ compi#ate9 i# co##e.amento di modu#i .ia/ precedentemente scritti con diversi #in.ua..i di ori.ine9 #a possi0i#ita/ di porre su# mercato- pro.rammi o modu#i non in 5orma ori.ine ma in 5orma o..etto9 e/ ,uesta #a sce#ta di mo#ti produttori per motivi di tute#a de##a proprieta/'
7# cic#o di svi#uppo dei pro.rammi rica#ca #e se.uenti 5asi che verranno e#encate: Preparazione testo origine:
7# testo ori.ine viene preparato mediante un editor e viene sa#vato con estensione 'cpp9 7# codice sor.ente di una app#icazione viene- in .enera#e- strutturata in piu/ modu#iredatti da piu/ pro.rammatori9 Ciascuna unita/ di traduzione viene sottoposta separatamente a##e successive 5asi di precompi#azione e compi#azione9
(irettive di precompi#azione9 (ichiarazioni di nomi di tipo9 (ichiarazioni di costanti e varia0i#i9 (ichiarazioni di 5unzioni BprototipiC9 (e5inizione di costanti e di varia0i#i9 (e5inizione di 5unzioni'
./Giuseppe_N3mes1s
<6>
7# testo ori.ine Bsor.enteC contenuto ne# 5i#e 'c/'cpp viene e#a0orato da un pro.ramma detto preprocessore Bprecompi#atoreC che modi5ica i# codice se.uendo a#cune direttive date.#i da# pro.rammatore9 Le direttive a# preprocessore sono contenute ne##e ri.he di testo che cominciano co# carattere # Bcance##etto- sharp- poundC9 L/output de# precompi#atore e/ codice sor.ente che va a# compi#atore vero e proprio'
Le unita/ de# pro.ramma ven.ono compi#ate separatamente mediante #/attivazione de# compi#atore9 Per ciascuna unita/ di traduzione- i# testo ori.ine viene tras5ormato in 5i#e o..etto e viene sa#vato in un 5i#e con estensione 'o0$ Boppure 'oC'
Il file oggetto
7# 5ormato de# 5i#e o..etto e/ indipendente da# #in.ua..io ad a#to #ive##o9 Un 5i#e contiene- o#tre a# codice macchina: ! una ta0e##a di sim0o#i B5unzioni e varia0i#i esterne o .#o0a#iC de5inite ne# corrispondente 5i#e sor.ete9 !! una ta0e##a dei sim0o#i uti#izzati ma non de5initi ne# modu#o B,uindi de5initi in a#tri modu#iC9
Collegamento (linkage)
7 diversi modu#i o..etti costituenti i# pro.ramma Bp1'o-''-pn'oC ven.ono com0inati 5ra #oro ed assieme a# supporto a tempo di esecuzione- mediante un pro.ramma co##e.atoreB#in%erC9 7# co##e.atore traduce i# testo ese.ui0i#e de# pro.ramma in un unico 5i#e Besempio: pro.'eFeC9 Anche se i# pro.ramma consta di un so#o 5i#e sor.ente- a#cune #i0rerie sono 5ondamenta#i Bad esempio ,ue##e di in.resso/uscitaC9 7# #in%er puo/ se.na#are errori- tipicamente perche/ non e/ possi0i#e associare ad un sim0o#o richiesto da un modu#o a#cun sim0o#o tra ,ue##i esportati nei modu#i9 Cio/ puo/ avvenire in a#cuni dei se.uenti casi: ./Giuseppe_N3mes1s
Guida C++: Aspetti Avanzati !! ci si e/ dimenticati di indicare ,ua#che 5i#e'cpp a# #in%er9 !! manca #/imp#ementazione di ,ua#che 5unzione9 !! esistono piu/ de5inizioni di uno stesso nome di 5unzione o varia0i#e .#o0a#e' Ambiente di sviluppo
<7>
Compi#atore9 Co##e.atore9
ditor9 Ana#izzatori/veri5icatori di codice9 Pro.ramma di .estione automatica dei passi di compi#azione e co##e.amento Bma%eC9 (e0u..er9 Pro.ramma di creazione di #i0rerie di modu#o o..etto9 Generatori automatici di codice9 6o5t2are di .estione de##a con5i.urazione so5t2are'
G#i am0ienti di svi#uppo inte.rati Bdetti 7( C ra..ruppano ta#i strumenti sotto un/unica inter5accia:
8or#and Eur0o Pasca# Binter5accia testua#e a menu/C9 8or#and C++ 8ui#der Binter5accia .ra5ica e pro.rammazione visua#eC9 (ev!C++ Binter5accia .ra5ica e pro.rammazione visua#eC9
Modularizzazione L/uso discip#inato di a#cuni meccanismi de# #in.ua..io C++ consente una corretta strutturazione di un pro.ramma in modu#i' Era i principi di meccanismo ci sono:
Guida C++: Aspetti Avanzati #/inc#usione testua#e9 #e dichiarazione extern9 #/uso dei prototipi di 5unzione9
<8>
Specifica ed implementazione / 0uona norma tenere separata #a speci5ica di un modu#o da##a sua imp#ementazione' Un pro.ramma utente di un modu#o A deve conoscere #a sua speci5ica- ma disinteressarsi dei detta.#i de##a sua imp#ementazione' Cio/ puo/ essere rea#izzato scrivendo un 5i#e di intestazione o header file Bcon estensione 'hC contenente #e dichiarazioni che costituiscono #/inter5accia di A- ed un 5i#e separato per #/imp#ementazione di A' L/header 5i#e deve essere inc#uso Bmediante #a direttiva a# preprocessore #includeC ne##a imp#ementazione- ed o.ni modu#o utente- a55inche/ i# compi#atore possa ese.uire i contro##i necessari' esempio: un pro.ramma C++ consiste di piu/ 5i#e sor.enti che sono individua#mente compi#ati in 5i#e o..etto- ,uesti poi sono co##e.ati tra #oro per produrre #a 5orma ese.ui0i#e' //fact.h long fact(long); //fact.cpp #include "fact.h" long fact(long f){ if(f<=1)return 1; return f* fact(f-1); } //main.cpp #include "fact.h" #include <io tream! int main(){ cout <<""attoriale (#)= "<<fact(#)<<"$n"; return %; } 6i noti- 5in tanto che #/inter5accia resta intatta- #/imp#emetazione puo/ essere modi5icata senza dover ricompi#are i# modu#o utente Bma occorre rico##e.are i modu#i o..ettoC' La speci5ica- contenuta ne# 5i#e di intestazione- puo/ essere .uardata come una sorta di contratto sottoscritto tra #/imp#ementatore e #/utente' Guando piu/ pro.rammatori #avorano simu#taneamente ad un pro.etto di .randi dimensioni- una vo#ta accordatisi su##a speci5ica dei vari modu#i- possono procedere ./Giuseppe_N3mes1s
Guida C++: Aspetti Avanzati a##/impe#ementazione dei ripettivi modu#i indipendentemente #/uno da##/a#tro' ibrerie dei moduli soft!are
<9>
Gueste tecniche di svi#uppo modu#are consentono #o svi#uppo su 0ase pro5essiona#e di #i0rerie di modu#i so5t2are9 7# produttore di una #i0reria distri0uisce:
i# 5i#e intestazione Bche devono essere inc#usi da##/uti#izzatore ne# codice sor.enteC dei modu#i che 5anno parte de##a #i0reria9 i modu#i de##a #i0reria in 5ormato o..etto B.ia/ compi#atiC- che #/uti#izzatore deve co##e.are assieme ai proprio modu#i o..etto9
Ea#e sce#ta e/ tipicamente motivata da esi.enze di tute#a de##a proprieta/- ed ino#tre evita di dover ricompi#are i modu#i di #i0reria' Perc"e' dividere il programma in piu' file sorgenti 7 vanta..i ne# dividere i# pro.ramma in piu/ modu#i ser.ente sono:
La struttura di un pro.ramma medio!.rande e/ piu/ chiara se i# pro.ramma e/ suddiviso in piu/ 5i#e sor.enti9 Piu/ pro.rammatori possono #avorare a##o stesso tempo su 5i#e diversi9 Non occorre ricompi#are #/intero pro.ramma o.ni vo#ta che si e55ettua una picco#a modi5ica9 6i possono usare #i0rerie senza dovere inc#udere 5isicamente i# codice sor.ente ne# pro.rammaBspesso i# sor.ente non e/ disponi0i#eC' 'inclusione multipla
6i puo/ veri5icare che #a stessa #i0reria ven.a inc#usa da due di55erenti #i0rerie entram0i inc#use- a #oro vo#ta- in uno stesso pro.ramma' 7n ,uesto caso- in assenza di precise precauzioni- si inc#udere00ero ne##a compi#azione piu/ copie de##o stesso codice Bcontenuto ne# 5i#e headerC- ra##entando i# processo di compi#azione' Poiche/ #/header 5i#e contiene esc#usivamente dichiarazioni- non ha a#cun vanta..io inc#uder#o piu/ vo#te' Precauzioni La precauzione per evitare #a dup#icazione di codice consiste ne##/uti#izzare opportunamente #e direttive di precompi#azione' 7 partico#are si usano #e direttive:
./Giuseppe_N3mes1s
<10>
#ifndef #define #endif sempio: #/header 5i#e de##a #i0reria iostream e/ rea#izzato cosi/:
//io tream.h #ifndef &'()*+,-.&/ #define &'()*+,-.&/ ... //0ui le dichiara1ioni della li2reria #endif /* &'()*+,-.&/ */ Guesto approccio e/ sempre uti#izzato da chi scrive #i0rerie' #nicita' delle etic"ette Nonostante cio/ riso#va i# pro0#ema- si rende necessario che ne##/am0ito di un intero pro.etto i nomi de##e etichetteB es: _7>6E; A"_HC siano univoci' 6e ,uesto re,uisito viene a mancare si possono .enerare errori dovuti a##a mancata inc#usioni de##e #i0rerie' Conflitti tra nomi 7n pro.etti di dimensioni medio!.randi e/ possi0i#e che ci siano con5#itti tra nomi esportati tra due di55erenti #i0rerie' Guesto 5enomeno e/ noto come Iin,uinamento de##o spazio dei nomiI' 7# C tenta di riso#vere i# pro0#ema attraverso #/uso di sim0o#i che Iaccompa.nanoI .#i identi5icatori:
$ic"iarare un namespace A #ive##o di modu#o e/ possi0i#e dichiarare un namespace ne# ,ua#e ven.ono poi de5initi tutti i sim0o#i de# modu#o: esempio: studenti'h #ifndef &&)*34,5*'&& #define &&)*34,5*'&& name pace p1tlc { t6pedef truct { ./Giuseppe_N3mes1s
Guida C++: Aspetti Avanzati int prefi o; int matricola; char* 7ognome; char* 5ome; } )tudente; e8tern )tudente +appre entante; } #endif /* &&)*34,5*'&& */ #tilizzare un namespace Per uti#izzare un nome de5inito ne##/am0ito di un namespace 0iso.na esp#icitamente IaprireI #o spazio dei nomi' 7n caso contrario si incorre in errori di compi#azione' esempi: #include " tudenti" int main() { )tudente ; //genera un errore.")tudente" non e9 un identificatore definito ... } #include " tudenti" int main() { p1tlc::)tudente ... }
<11>
; //(;<
#include " tudenti u ing name pace )tudenti; //"apre" tutto lo int main() { )tudente ; //(;< ... } Lo standard C++
Convenziona#mente- in C++ .#i header 5i#e i cui nomi terminano con 'h non 5anno uso dei namespace' Gue##i invece che non hanno estensione- a# contrario- #i usano' La #i0reria standard- ,ue##a che de5inisce anche cin e cout- de5inisce tutti i sim0o#i ne##o spazio dei nomi std' esempi: // tile c #include <io tream.h! int main() { ./Giuseppe_N3mes1s
Guida C++: Aspetti Avanzati cout << ""un1iona<$n"; } //errore #include <io tream! int main() { cout << "5on fun1iona<$n"; } // tile c== con ri olutore di cope #include <io tream! int main() { td::cout << ""un1ion>o tandard 7==
<12>
Convenziona#mente- in C++ .#i header 5i#e i cui nomi terminano con 'h non 5anno uso dei namespace' Gue##i invece che non hanno estensione- a# contrario- #i usano' La #i0reria standard- ,ue##a che de5inisce anche cin e cout- de5inisce tutti i sim0o#i ne##o spazio dei nomi std' esempi: // tile c #include <io tream.h! int main() { cout << ""un1iona<$n"; } //errore #include <io tream! int main() { cout << "5on fun1iona<$n"; } // tile c== con ri olutore di cope #include <io tream! int main() { td::cout << ""un1iona<$n"; } // tile c== con diretti?a u ing #include <io tream! u ing name pace td; int main() { cout << ""un1iona<$n"; }
./Giuseppe_N3mes1s
<13>
a %icorsione
7# concetto di ricorsione in5ormatica si riconduce a# concetto di induzione matematica' 6ia P un predicato su##/insieme N dei numeri natura#i e sia vero i# predicato PB)C9 se per o.ni J intero- da# predicato PBJC discende #a verita/ di PBJ+1C a##ora PBnC e/ vero in ,ua#siasi n' La dimostrazione de##a 5orma induttiva viene dun,ue svo#ta secondo i se.uenti passi: Passo 0ase de##/induzione: dimostrare PB)CKvero9 Passo induttivo: dimostrare che per o.ni %L) PB%C !L PB%+1C Cosi/ come ne##a 5unzione induttiva #a verita/ di PB%+1C descende da##a verita/ de##o stesso predicato di PB%C- i# ca#co#o di una 5unzione ricorsiva avviene mediante i# ca#co#o de##a stessa 5unzione in un passo successivo' %icorsione 7# ca#co#o ricorsivo sta ne# 5atto di ca#co#are una 5unzione attraverso se stessa' esempio: #a 5unzione 5attoria#e N3 Bper interi non ne.ativiC aC)3K1 0Cse nL) a##ora n3 KnMBn!1C3 7n a#tre paro#a #a potenza de##a ricorsione sta ne# 5atto di poter de5inire un insieme in5inito di o..etti con una re.o#a 5inita' A#.oritmi ricorsivi 6ono caratterizzati da: Una 5unzione .eneratrice ! F'''K.BF'C ! che produce una se,uenza di F'-F'-F'- '''- F' Un predicato pK pBFC vero per FKF' Una 5unzione 5BFC detta ricorsiva ta#e che ! 5BF'CKcNhBF'C-5BF''CO ! 5BF'CK 5Bse.natoC Sc"ema di algoritmi ricorsivi 6ono codi5icati mediante un sottopro.ramma che richiama se stesso: @ (*1 8) { ... if p(8) "; ./Giuseppe_N3mes1s
Guida C++: Aspetti Avanzati el e 7()A@); + } int fatt(int 8){ int f; if(8<=1) f=1; el e f=8*fatt(8-1); return f; } &erminazione
<14>
La chiamata ricorsiva deve ,uindi essere su0ordinata ad una condizione che ad un certo istante risu#ti non soddis5atta Bi# predicato pC' 7# numero de##e chiamate necessarie viene detto pro5ondita/ de##a ricorsione' Meccanismo interno della ricorsione Un sottopro.ramma ricorsivo e/ un sottopro.ramma che richiama direttamete o indirettamente se stesso' Non tutti i #in.ua..i rea#izzano i# meccanismo di ricorsione' Gue##i che #o uti#izzano 5anno uso di ,ueste tecniche:
Gestione L7<> di piu/ copie de##a stessa 5unzione- ciascune con i# proprio insieme di varia0i#i #oca#i .estione mediante record di attivazione9 un/unica copia de# sottopro.ramma ma ad o.ni chiamata e/ associata ad un record di attivazione'
$alla forma ricorsiva a 'uella iterativa Un pro0#ema ricorsivo puo/ essere riso#to in 5orma iterativa' Ne# caso in cui #a ricorsione e/ in coda i# caso e/ semp#ice: ricorsivo: @(*1 8) { ... if p(8) "; el e{);@(8);} return } iterativo: Bhile <p(8) ./Giuseppe_N3mes1s
Guida C++: Aspetti Avanzati ); "; ca#co#o de# 5attoria#e: esempio: 5orma ricorsiva: int fatt(con t int 8){ int f; if (8<1) f=1 el e f=8*fatt(8-1); return f; } 5orma iterativa: int fatt(con t int 8){ int f=1Ai; for(i=1;i<8;i==) f=f*i; return f; } %icorsione ed iterazione ;icorsione:
<15>
7terazione: Uso de# costrutto di iterazione Condizione di terminazione Loop in5inito A di55erenza de##/iterazione- #a ricorsione richiede un notevo#e sovreccarico BoverheadC a tempo di esecuzione per #a chiamata di 5unzione' (uando usare)non la ricorsione A#.oritmi che per #a #oro natura sono ricorsivi piuttosto che iterativi dovre00ero essere 5ormu#ati con procedure ricorsive' Ad esempio a#cune strutture dati sono inerentemente ricorsive: ! 6trutture ad a#0ero ! 6e,uenze ./Giuseppe_N3mes1s
Guida C++: Aspetti Avanzati ! ''' #a 5ormu#azione di strutture ricorsive su di esse risu#ta piu/ natura#e'
La ricorsione deve essere evitata ,uando esiste una so#uzione iterativa ovvia e in situazioni in cui #e prestazioni de# sistema son un e#emento critico
<16>
Guida C++: Aspetti Avanzati Un parametro di ri5erimento e/ un a#ias de##a varia0i#e ar.omento' 7# passa..io per ri5erimento e/ e55iciente in ,uanto evita #a copia de# va#ore'
<17>
7# parametro 5orma#e in rea#ta/ e/ un puntatore che contiene #/indirizzo di ri5erimento de# parametro e55ettivo' 7# passa..io de##/indirizzo Bdere5erencin. de# ri5erimentoC e/ a cura de# compi#atore' ?oid incr(int D?) { ? == 1; } int a = C; incr (a); // ora "a" ?ale E I riferimenti 7 ri5erimenti sono in ,ua#che modo e,uiva#enti a dei puntatori costanti: CP r e,uiva#e a CM const p
La di55erenza sta ne# 5atto che ne# caso dei ri5erimenti e/ #asciato a# compi#atore i# compito di distin.uere tra i# ri5erimento ed i# va#ore ri5erito9 ne# caso dei puntatori i# pro.rammatore deve esp#icitamente indicare dove vuo#e operarese su# puntatore o su# va#ore puntato' L/uso dei ri5erimento e/ dun,ue meno inc#ine a.#i errori' ssi devono rispettare #e se.uenti re.o#e: ! un ri5erimento deve essere inizia#izzato ,uando e/ creato ! una vo#ta creato un ri5erimento non puo/ essere modi5icato ! non e/ possi0i#e avere un ri5erimento NULLB)C esempio: int 8; int D r = 8; //r e9 un riferimento ad 8 r=F; // r e9 un l-?alue e dun0ue un indiri11o int G=r; // r e9 un r-?alue e dun0ue un ?alore ,li argomenti di dafault G#i ut#imi oppure tutti i parametri di una #ista possono avere dei va#ori di da5au#t' / i# prototipo che deve speci5icare .#i ar.omenti di de5au#t' 6e #/invocazione de##a 5unzione non speci5ica .#i u#timi ar.omenti- ,uesti ven.ono assunti u.ua#i a.#i ar.omenti di da5ua#t' esempio: ./Giuseppe_N3mes1s
Guida C++: Aspetti Avanzati ?oid a2c(int 8A int 6=1A char *p="hello"); ... ?oid 861() { a2c(1A "6aht1ee<");//il compilatore a parametro 6 e egnala errore } 'overloading delle funzioni
<18>
ocia 6aht1ee al
7n C++ e/ possi0i#e dare a 5unzioni diverse #o stesso nome- a condizioni che #e 5unzioni a00iano #iste di parametri diversi Bin numero e/o tipoC' 7# compi#atore e/ in .rado di associare in modo univoco ciascuna chiamata a una de##a 5unzioni- distinte in 0ase a##a #ista de.#i ar.omenti' esempio: // ?er ione ?oid incr(int *?) { *?==; } // ?er ione H ?oid incr(int *?A int d8) { *? == d8; } // ?er ione 7 ?oid incr(float *?) { *? = *? = 1.%; } float 8=%.; incr(8); // ?iene in?ocata // la ?er ione 7 Avere tipi di ritorno diversi non e/ su55iciente a distin.uere #e 5unzioni' Ne##/istruzione di chiamata in5atti puo/ non essere evidente i# tipo de# va#ore di ritorno' Un uso poco attento dei parametri di de5au#t puo/ causare am0i.uita/' ?oid o?l(char=9a9); ?oid o?l(int=%); III o?l(); Guando uno stesso nome e/ associato a piu/ 5unzioni- si dice che ,uesto nome e/ sovraccaricato Bover#oadedC di si.ni5icato' <7;"A Bsi.natureC di una 5unzione: ./Giuseppe_N3mes1s
<19>
nome + tipo dei parametri 7n presenza de##a chiamata di una 5unzione over#oaded- i# compi#atore riconosce ,ue##a me.#io adatta a##a chiamata 7# tipo restituito non 5a parte de##a 5irma de##a 5unzione'
L/over#oadin. de##e 5unzioni si usa: Guando si devono de5inire 5unzioni concettua#mente simi#i da ap##icare a dati di tipo diverso L/a#.oritmo uti#izzato da ciascuna 5unzione e/ anch/esso diverso a seconda dei tipi di dato a cui #a 5unzione deve essere app#icata' e funzioni inline Le 5unzioni in#ine sono 5unzioni #a cui chiamate non sono tradotte in #in.ua..io macchina da# compi#atore mediante sa#to a sottopro.ramma 7# codice de##a 5unzione viene inserito in #inea- cioe/ ne# punto de##a chiamata L/uso de##e 5unzioni in#ine deve essere #imitato a 5unzioni da# corpo mo#to 0reve a#trimenti: i# mi.#ioramento de# tempo di esecuzione e/ irri#evante #/aumento de##a dimensione de# codice puo/ essere notevo#e Le 5unzioni in#ine devono essere de5inite ne##o stesso 5i#e in cui sono invocate- ovvero in un 5i#e di intestazione Bheader 5i#eC da importare- perche/ i# compi#atore deve conoscerne i# corpo per sostituir#o ad o.ni chiamata: non sempre una 5unzione in#ine viene svi#uppata in #inea da# compi#atore non puo/ essere esportata Una 5unzione in#ine puo/ speci5icare ar.omenti di da5au#t: inline int plu (ne(int 8=%) { return ==8; } int main() { cout <<"$n inline:"<<plu (ne(); 6 tem("@-3),"); return %; }
'Astrazione ./Giuseppe_N3mes1s
Guida C++: Aspetti Avanzati L/astrazione e/ i# processo che porta ad estrarre #e proprieta/ ri#evanti di un/entita/in.norando pero/ i detta.#i inessenzia#i' Le propieta/ estratte de5iniscono una vista de##/entita/9 Una stessa entita/ puo/ dar #uo.o a viste diverse9 a Modularita'
<20>
La modu#arita/ e #/or.anizzazione in modu#i di un sistema- in modo che #o stesso risu#ti piu/ semp#ice da capire e manipo#are' Un modu#o di un sistema so5t2are e/ un componente che: rea#izza un/astrazione9 e/ dotata di una chiara separazione tra: ! inter5accia9 ! corpo9 L/inter5accia speci5ica cosa 5a i# modu#o e come si uti#izza' 7# corpo descrive come #/astrazione e/ rea#izzata' 'incapsulamento e information "iding L/incapsu#ameno consiste ne# InascondereI e Iprote..ereI a#cune in5ormazioni di un/entita/' L/accesso in maniera contro##ata a##e in5ormazioni nascoste e/ poss0i#e .razie a varie operazione descritte da##/inter5accia' 'importanza delle astrazioni Eutti i #in.ua..i di pro.rammazione o55rono diversi tipi di astrazione:
L/astrazione 5ondamenta#e dei #in.ua..i ad o..etti e/ #/astrazione sui dati' Meccanismi di astrazione Ne##a pro.ettazione di un sistema so5t2are e/ opportuno adoperare de##e tecniche di astrazione atte a dominare #a comp#essita/ de# sistema da rea#izzare' 7 meccanismi di astrazione piu/ di55usi sono:
./Giuseppe_N3mes1s
Guida C++: Aspetti Avanzati Astrazione sul controllo Consiste ne##/astrarre una data 5unziona#ita/ nei detta.#i de##a sua imp#ementazione9 / 0en supportata dai #in.ua..i di pro.rammazione attraverso i# concetto di sottopro.ramma' Astrazione sui dati
<21>
Consiste ne##/estrarre entita/ Bo..ettiC constituenti i# sistema- descritte in termini di una struttura dati e de##e operazioni possi0i#i su di essa9 Puo/ essere rea#izzata con uso opportuno de##e tecniche di pro.ramazione modu#are nei #in.ua..i tradiziona#i9 / supportata da appositi costrutti nei #in.ua..i di pro.rammazione ad o..etti' Metodologie di progetto+ &op.$o!n e /ottom.#p La metodo#o.ia discendente- cioe/ top!do2n- e/ 0asata su##/approccio di decomposizione 5unziona#e ne##a de5inizione di in sistema so5t2are- cioe/ su##/individuazione de##e 5unziona#ita/ de# sistema da rea#izzare e su ra55inamenti successivi- da iterare 5inche/ #a scomposizione de# sistema individua sottoinsieme di comp#essita/ accetta0i#i' La metodo#o.ia ascendente- cioe/ 0ottom!up- e/ 0asata su##/individuazione de##e entita/ 5acenti parte de# sistema- de##e #oro proprieta/ re#azioni tra di esse' 7# sistema viene costruitoassem0#ando componenti on un/approccio da# 0asso verso #/a#to' a programmazione procedurale Usa come metodo#o.ia di ri5erimento #a decomposizione 5unziona#e- con approccio discendente ,uindi top!do2n' 6i scompone ricorsivamente #a 5unziona#ita/ principa#e de# sistema da svi#uppare in 5unziona#ita/ piu/ semp#ici' 6i termina #a scomposizione ,unado #e 5unziona#ita/ individuate sono cosi/ semp#ici da permettere una diretta imp#ementazione come 5unzioni' 6i divide i# #avoro di imp#ementazione- eventua#mente tra diversi pro.rammatori- su##a 0ase de##e 5unziona#ita/ individuate' a programmazione ad oggetti 6i individuano #a c#assi di o..etti che caratterizzano i# dominio app#icativo: #e diverse c#assi ven.ono poi mode##ate- pro.ettate ed imp#ementate9 o.ni c#asse e/ descritta da un/inter5accia che speci5ica i# comportamento de.#i o..etti de##a c#asse' L/app#icazione si costituisce con #/approciio ascendente- 0ottom!up- assem0#ando o..etti e individuando #a moda#ita/ con cui ,uesti devono co##a0orare per rea#izzare #e 5unziona#ita/ deverse de##/app#icazione' ./Giuseppe_N3mes1s
<22>
&ipi di dati astratti 7# concetto di tipo di dato in un #in.ua..io di pro.rammazione tradiziona#e e/ ,ue##o di insieme dei va#ori che un dato puo/ assumere Bvaria0i#eC' 7# tipo di dati stratto inc#ude in ,uesto insieme- estendendone #a de5inizione- anche #/insieme di tutte e so#e #e operazioni possi0i#i su dati di ,ue# tipo' La struttura dati comp#eta e/ incapsu#ata ne##e operazione da essa de5inite' Non e/ possi0i#e accedere a##a struttura dati incapsu#ata- ne in #ettura ne in scrittura- se non con #e operazioni de5inite su di essa ' 7nter5accia: speci5ica de# E(ABtipo dato astrattoC- descrive #a parte direttamente accessi0i#e da##/uti#izzatore9 ;ea#izzazione: imp#ementazione de# E(A' Produttore e utilizzatore 7# c#iente 5a uso de# E(A per rea#izzare procedura di un/app#icazione- e per costruire E(A piu/ comp#essi9 7# Produttore rea#izza #e astrazioni e #e 5unziona#ita/ previste per i# dato' Una modi5ca ao#a a##a rea#izzazione de# E(A non in5#uenza i modu#i che ne 5anno uso' &ecnic"e di programmazione ad oggetti 6i par#a di pro.rammazione con o..etti con ri5erimento a tecniche di pro.rammazione 0asate su# concetto di o..etto' 6i par#a di pro.rammazione 0asata su.#i o..etti Bo0$ect!0ased pro.rammin.C con ri5erimento a##e tecniche di pro.rammazione 0asate sui concetti di: Eipo di dato astratto o C#asseBtipoC9 >..etto Bistanza de# tipoC' 6i par#a di pro.rammazione orientata a.#i o..ettiBo0$ect oriented pro.rammin.- >>PC co ri5erimento a##e tecniche 0asate sui concetti: C#asse9 >..etto9 reditarieta/9 Po#imor5ismo' inguaggi ad oggetti / possi0i#e adottare tecniche di pro.rammazione con o..etti o 0asate su.#i o..etti anche in #un.ua..i tradiziona#iBpasca#- cC adoperando opportune discip#ine di pro.rammazione- aderendo cioe/ ad un insieme di re.o#e i# cui uso pero/ non puo/ essere ne ./Giuseppe_N3mes1s
<23>
Un #in.ua..i di pro.rammazione ad o..etti o55re costrutti esp#iciti per #a de5inizione di entita/- o..etti- che incapsu#ano #a struttura dati ne##e operazioni su di essa' A#cuni #in.ua..i- in partico#are i# C++- consentono di de5inire tipo astratti- e ,uindi istanze di un dato di tipo astratto' 7n ta# caso i# #in.ua..io 0asato su.#i o..etti presenta costrutti per #a de5inizione di c#assi e di o..etti' sistono dun,ue #in.ua..i ad o..etti: Non tipizzati: s 6ma##ta#% / possi0i#e de5inire o..etti senza dichiararne i# tipo 7n ta#i #in.ua..i .#i o..etti sono entita/ che incapsu#ano una struttura dati ne##e operazioni possi0i#i su di essa' Eipizzati: s C++- Rava / possi0i#e de5inire tipo di dati astratti ed istanziar#i' G#i o..etti devono appartenere ad un tipo' 7n ta#i #in.ua..i- una c#asse e/ una imp#ementazione di un tipo di dato astratto' Un o..etto e/ una istanza di una c#asse' Il linguaggio C++ C++ e/ un #in.ua..io di pro.rammazione .enera#!purpose che supporta: La pro.rammazione procedura#e La pro.rammazione orientata a.#i o..etti La pro.rammazione .enerica 7# c++ e/ dun,ue un #in.ua..io Ii0ridoI ne# senso che supporta piu/ paradi.mi di pro.rammazione' Classi ed oggetti Ne# #in.ua..i a o..etti- i# costrurro c#asse consente di de5inire nuovi tipi di dati astratti e #e re#ative operazione connessi ad essi' 6otto 5orma di operatori o di 5unzioni Bdette 5unzioni mem0roC- i nuovi tipi di dato possono essere .estiti ,uasi a##o stesso modo dei tipi prede5initi da# #in.ua..io: si possono creare istanze9 si possono ese.uire operazioni su di esse9 Un o..etto e/ una varia0i#e istanza di una c#asse' Lo stato di un o..etto e/ rappresentato dai va#ori de##e varia0i#i che costituiscono #a ./Giuseppe_N3mes1s
Guida C++: Aspetti Avanzati struttura dati concreta sottostante i# tipo astratto' 0reditarieta' e Polimorfismo
<24>
L/ereditarieta/ consente di de5inire nuove c#assi per specia#izzazioni o estensioni per c#assi .ia/ preesistenti- in modo incrementa#e' 7# po#imor5ismo consente di invocare operazioni su un o..etto- pur non essendo nota a tempo di compi#azione #a c#asse a cui 5a ri5erimento #/o..etto stesso' 0reditarieta' 7# mecaniscmo di ereditarieta/ e/ 5ondamenta#e ne##a pro.rammazione ad o..etti- in ,uanto prevede #a strutturazione .erarchica ne# sistema so5t2are da costruire' L/ereditarieta/ in5atti consente di rea#izzare re#azioni tra ca#ssi di tipo .enera#izzazione! specia#izzazione- in cui- una c#asse- detta 0ase- rea#izza i# comportamento .enera#e comune ad un insieme di entita/- mentre #a c#assi derivate rea#izzano comportamenti specia#izzati rispetto a ,ue##i de##a c#asse 0ase' Genera#izzazione: da# partico#are a# .enera#e 6pecia#izzazione o partico#arizzazione: da# .enera#e a# partico#are siste pero/ un a#tro motivo per uti#izzare #/ereditarieta/ o#tre a ,ue##o di or.anizzazione .erarchica- ed e/ ,ue##o de# riuso de# so5t2are' 7n a#cuni casi si ha una c#asse che non corrisponde proprio a##e nostre esi.enze- anziche/ scartare i# tutto e riscrivere i# codice- con #/ereditarieta/ si puo/ se.uire un approccio diverso- costruendo una nuova c#asse che eredita i# comportameto di ,ue##a esistente- sa#ve pero/ che per ,uei com0iamenti che si ritiene necessario apportare' Ea#i cam0iamenti posso portatre a##/a..iunta/ di nuove 5unziona#ita/ o a##a modi5ica di ,ue##e esistenti' 7n de5initiva #/ereditarieta/ o55re un vanta..io anche in termini di svi#uppo perche/ riduce i tempi- in ,uanto: minimizza #a ,unatita/ di codice da scrivere non e/ necessario conoscere in detta.#io i# 5unzionamento de# codice da riuti#izzare ma e/ su55iciente modi5icare #a parte di interesse' Polimorfismo Per po#imor5ismo si intende #a propieta/ de##/entita/ di assumere 5orme diverse ne# tempo' Con un/entita/ po#imor5a si puo/ 5are ri5erimento a c#assi diverse' 6i consideri una 5unzione (ise.na_<i.ureBC- che contiene i# se.uente cic#o di istruzioni: for i = 1 to 5 do -J i K.di egna() ./Giuseppe_N3mes1s
<25>
L/esecuzione de# cic#o richiede che sia possi0i#e determinare dinamicamente Bcioe/ a tempo d/esecuzioneC #/imp#ementazione de##a operazione dise.naBC da ese.uire- in 5unzione de# tipo corrente de##/o..etto AN i O' L/istruzione AN i O'dise.naBC non ha 0iso.no di essere modi5icata in conse.uenza de##/a..iunta di una nuova sottoc#asse di <i.ura Bad es': CerchioC- anche se ta#e sottoc#asse non era stata neppure prevista a##/atto de##a stesura de##a 5unzione (ise.na_<i.ureBC' 7# po#imor5ismo dun,ue supporta #a proprieta/ di estensi0i#ita/ di un sistema- ne# senso che minimizza #a ,uiantita/ di codice che occorre modi5icare ,uando si estende un sistemacioe/ si introducono nuove c#assi e nuove 5unziona#ita/' Un meccanismo con cui viene rea#izzato i# po#imor5ismo e/ ,ue##o de# 0indin. dinamico 7# 0indin. dinamico Bo #ate 0indin.C consiste ne# determinare a tempo d/esecuzioneanziche/ a tempo di compi#azione- i# corpo de# metodo da invocare su un dato o..etto' 1antaggi della programmazione -;ispetto a##a pro.rammazione tradiziona#e- #a pro.rammazione o0$ect oriented o55re vanta..i in termini di:
modu#arita/: #a c#assi sono i modu#i de# sistema so5t2are9 coesione dei modu#i: una c#asse e/ un componente so5t2are 0en coeso in ,uanto rappresentazione di un unica entita/9 disaccopiamento dei modu#i: .#i o..etti hanno un a#to .rado di disaccoppiamento in ,uanto i metodi operano su##a struttura dati interna ad un o..etto9 i# sistema comp#essivo viene costruitocomponendo operazioni su.#i o..etti9 in5ormation hidin.: sia #e strutture dati che .#i a#.oritmi possono essere nascosti a##a visi0i#ita/ da##/esterno di un o..etto9 riuso: #/ereditarieta/ consente di riusare #a de5inizione di una c#asse ne# de5inire nuove BsottoCc#assi9 ino#tre e/ possi0i#e costruire #i0rerie di c#assi ra..ruppate per tipo#o.ia di app#icazioni9 estensi0i#ita/: i# po#imor5ismo a.evo#a #/a..iunta di nuove 5unziona#ita/ minimizzando #e modi5iche necessarie a# sistema esistente ,uando si vuo#e estender#o'
0reditarieta'
'ereditarieta' nella programmazione soft!are L/ereditarieta/ e/ di 5ondamenta#e importanza ne##a pro.ettazione ad o..etti- poiche/ induce ad una strutturazione di tipo .erarchico ne# sistema so5t2are ./Giuseppe_N3mes1s
<26>
da rea#izzare' ssa consente in5atti di rea#izzare ,ue# sistema detto .erarchia di .enera#izzazione!specia#izzazione- seconda #a ,ua#e esiste #a c#asse- detta 0ase- che rea#izza i# comportamento .enera#e- comune ad un inseme di entita/- mentre #e c#assi derivate rea#izzano i# comportamento partico#are de.#i o..etti de##a .erarchia- specia#izzando#o rispetto a ,ue##o de##a 0ase' Ciascun o..etto de##a c#asse derivata e/ anche o..etto de##a c#asse 0ase ed eredita cosi/ tutti i comportamenti de##a c#asse 0ase ed in piu/ a..iun.e i comportamenti imp#ementati in essa' Non e/ vero i# contrario invece' 'ereditarieta' come riuso del soft!are siste pero/ anche un a#tro motivo- di ordine pratico- per cui conviene usare #/ereditarieta/' >#tre a ,ue##o di descrivere un sistema secondo un ordine .erarchico- ce un a#tro concetto che e/ #e.ato a# riuso de# so5t2are' 7n a#cuni casi si ha a disposizione una c#asse che non corrisponde propriamente a##e nostre esi.enze9 anziche/ scartare tutto i# codice esistente e riscriver#o- si puo/ se.uire con #/ereditarieta/ un approccio diverso- costruendo una nuova c#asse che eredita i# comportamento di ,ue##a esistenza- pero/ adattando#a a##e nostre esi.enze' Guesto approccio o55re i# vanta..io di ridurre i tempi de##o svi#uppo de# sot2are- perche/ minimizza #a ,uantita/ di codice da scrivere- riducendo anche #a possi0i#ita/ di cadere in errori' 7no#tre non e/ necessari conoscere i# 5unzionamento de# codice comp#essivo- ma e/ su55iciente modi5icare #a parte di interesse' 7n5ine poiche/ i# so5t2are e/ .ia/ stato veri5icato- #a parte di test risu#ta semp#i5icata' I meccanismi sintattici per la derivazione 6truttura de##a c#asse derivata 6upponiamo che sia stata de5inita una c#asse 0ase: <i#e 8ase'h cla Ha e{ pu2lic: //fun1ioni mem2ro " ?oid f1(); //fun1ione mem2ro f1 .... ?oid fn(); //fun1ione mem2ro fn pri?ate: //?aria2ili mem2ro alfa }; 7# pro.ettista di una nuova c#asse- di nome (erivata- puo/ de5inire #a nuova c#asse ,ua#e derivata de##a c#asse 8ase: <i#e (erivata'h ./Giuseppe_N3mes1s
Guida C++: Aspetti Avanzati #include "Ha e.h" cla e deri?ata:pu2lic Ha e{//deri?ata ereditata da Ha e //fun1ioni mem2ro L ?oid g1();//fun1ione mem2ro g1 ... ?oid gm();//fun1iome me2ro gm pri?ate: //?aria2ili mem2ro 2eta }; #a c#asse (erivata eredita tutte #e 5unzioni e #e varia0i#i mem0ro de##a c#asse 8ase e de5inisce a sua vo#ta u#teriori varia0i#i mem0ro 0eta e 5unzioni G' Meccanismi e diritti di accesso Aspetto generale
<27>
pu2lic:
Per ,uanto ri.uarda i diritti di accesso- va#e i# concetto .enera#e secondo i# ,ua#e nessun meccanismo puo/ vio#are #e protezioni de5inite da# pro.ettista de##a c#asse' 7n partico#are- una c#asse derivata non possiede nessun privi#e.io specia#e per accedere a##a parte private de##a c#asse 0ase: se cosi/ 5osse si potre00e in5ran.ere #a privatezza di una data c#asse semp#icemente de5inendo una c#asse derivata ad essa' La c#asse derivata dun,ue eredita varia0i#e e 5unzioni mem0ro de##a c#asse 0ase ma accede a ta#i comportamenti secondo i meccanismi che sono stati speci5icati ne##a c#asse 0ase' Le 5unzioni mem0ro de##a c#asse derivata possono accedere: a tutti i mem0ri de##a c#asse derivata- indipendentemente da##a #oro moda#ita/ di protezione ai mem0ri pu00#ici de##a c#asse 0ase Accesso delle funzioni membro e funzioni utente Per ,uanto attiene i# pro.ramma che uti#izza #a .erarchia di derivazione- esso puo/ de5inire o..etti de##a c#asse 0ase e o..etti de##a c#asse derivata e accedere- secondo i consueti meccanismi di accesso- a##e componenti pu00#iche di 8ase e (erivata' 7no#tre uti#izzando i meccanismi 5orniti da##/ereditarieta/- i# pro.ramma utente puo/ accedere a##a componenti pu00#iche de# sotto!o..etto 0ase de##a c#asse derivata e puo/ app#icare a ,uest/u#timo #a 5unzioni de5inite da##a c#asse 0ase'
Le 5unzioni mem0ro di 8ase accedono ai componenti pu00#ici e privati de# sotto! o..etto 0ase9 Le 5unzioni mem0ro de##a (erivata accedono a componenti pu00#ici de# sotto! o..etto 0ase e ai componenti pu00#ici e privati de##a parte proprio di (erivata9 Le 5unzioni utente di (erivata accedono a componenti pu00#ici de# sotto!o..etto ./Giuseppe_N3mes1s
Guida C++: Aspetti Avanzati 0ase e de##a parte propria di derivata' -verriding e -verloading
<28>
7# meccanismo di ride5inizione viene detto overridin. de##e 5unzioni Bsovrapposizione con preva#enzaC ed e/ un meccanismo addiziona#e e diverso rispetto a# sovraccarico de##a 5unzioni Bover#oadin.C' 7# primo prevede che ne##a c#asse derivata una 5unzione ven.a ride5inita con 5orma identica a ,ue##a de##a c#asse 0ase e che #/o..etto de##a c#asse derivata sia app#icata #a 5unzione ride5inita- in secondo prevede viceversa che due 5unzioni a00iano nome u.ua#e ma 5irma diversa e che i# compi#atore sce#.a #a 5unzione da chiamare su##a 0ase de# mi.#ior adattamento a##a 5orma de##/istruzione chiamata' 7 due meccanismi possono coesistere ne##e c#assi derivate- ne# senso che una c#asse derivata ride5inisce una 5unzione 5BC de##a c#asse 0ase due vo#te- con #a medesima 5irmaBoverridin.C e con 5irma diversaBover#oadin.C' Pera#tro #/impie.o dei due meccanismi rischia di compromettere #a #e..i0i#ita/ de# codice' Modalita' di derivazione privata <ino ad ora a00iamo visto #e moda#ita/ di derivazione pu00#iche' / pera#tro prevista anche una moda#ita/ di derivazione privata: cla Ha e{ pu2lic: ?oid f1(); //fun1ione mem2ro f1 ?oid fM(); //fun1ione mem2ro fM int m1; //?aria2ile mem2ro pu22lica pri?ate: int mM;//?aria2ile mem2ro pri?ata }; <i#e (erivata'h #include "Ha e.h" cla 4eri?ata: pri?ate Ha e{ //4eri?ata ereditata nella forma pri?ata pu2lic: ?oid g1(); //fun1ione me2ro g1 //accede a mem2ri pu22lici e pri?ati di 4eri?ata n1AnMAfM() //accede a mem2ri pu22lici di Ha e m1Af1()AfM() //non accede a mem2ri pri?ati di Ha e mM ?oid fM();//ridefini ce fM di Ha e int n1;//?aria2ile mem2ro pu22lica pri?ate: int nM;//?aria2ile mem2ro pri?ata }; ./Giuseppe_N3mes1s
<29>
La moda#ita/ di derivazione non ha ri5erimento ai diritti di accesso de##a c#asse derivata a##e componenti de##/o..etto di appartenente a##a c#asse 0ase- ma piuttosto a##a trasmissione dei diritti di acceso a##e componenti de##a c#asse 0ase a##e u#teriori c#assi derivate e a##e 5unzioni che uti#izzano o..etti de##a c#asse derivata' La moda#ita/ di derivazione privata 0#occa #/ereditarieta/- ne# senso che sia #e successive c#assi derivate sia #e 5unzioni utente non possono accedere a##e componenti de##a c#asse 0ase' esempio: <i#e 8ase'h cla Ha e{ pu2lic: ?oid f1(); //fun1ioni mem2ro f1 ?oid fM();//fun1ioni mem2ro fM int m1;//?aria2ile mem2ero intera pri?ate: int mM;?aria2ile mem2ro pri?ata }; <i#e (erivata'h #include "Ha e.h" cla 4eri?ata:pu2lic Ha e{ //deri?ata erediatata da 2a e pu2lic: ?oid g1();//fun1ione mem2ro g1 //accede a mem2eri pu22lici e pri?ati di 4eri?ata n1AnMAfM() //accede a mem2eri pu22lici di Ha e m1Af1()AfM() //non accede a mem2ri pri?ati di Ha e mM ?oid fM();//ridefini ce fM di Ha e int n1;/#?aria2ile mem2ro pu22lica pri?ate: int nM;//?aria2ile mem2ro pri?ata }; Le 5unzioni mem0ro de##a c#asse derivata possono accedere a##a componente privata di 8ase m* so#o attraverso #e 5unzioni di accesso- se de5inite da# pro.ettista de##a c#asse' Ampliamento dei meccanismi di protezione e di derivazione A##o scopo di concedere speci5ici privi#e.i di accesso a##e c#assi derivate- i# C++ ha amp#iato #e moda#ita/ di protezione e di derivazione- prevedendo o#tre a##a moda#ita/ pu00#ica e privata- #a moda#ita/ di protezione e di derivazione protetta' ./Giuseppe_N3mes1s
<30>
7 mem0ri protetti di una c#asse 8 sono accessi0i#i a##a c#asse derivata ( ma non a.#i utenti di 8 o (' La derivazione protetta rende #a c#asse accessi0i#e da a#tre c#assi ma non da.#i utenti di ,ueste' Per ,uanto attiene a##e moda#ita/ di derivazione e di protezione si opera tipicamente come:
#a moda#ita/ di derivazione viene de5inita pu00#ica- a##o scopo di consentire #a trasmissione dei diritti di accesso a##e successive c#assi de##a .erarchia e a.#i utenti9 #e 5unzioni mem0ro ven.ono de5inite pu00#iche- a##o scopo di consentire a.#i utenti de##a .erarchia di derivazione di app#icare i metodi richiesti a.#i o..etti de##a .erarchia9 #e varia0i#i mem0ro ven.ono de5inite protette- a##o scopo di consentire #/accesso a##a struttura dati a tutte #e c#assi de##a .erarchia di derivazione ma non a.#i utenti'
Guesto e/ in un caso .enera#e- ma possono essere amp#iate anche con a..iunta di a#tre accortezze:
a#cune 5unzioni mem0ro possono essere dichiarate private se si tratta di 5unzioni di servizio che devono essere uti#izzate so#o a##/interno di una c#asse9 a#cune 5unzioni mem0ro possono essere dichiarate protette se si tratta di 5unzioni di servizio che devono essere uti#izzate so#o da 5unzioni mem0ro de##e c#assi derivate ma non da.#i utenti'
esempio: <i#e 8ase'h cla Ha e{ pu2lic: //fun1ioni mem2ro protected: //?aria2ili mem2ro }; <i#e (erivata'h #include "Ha e.h" cla 4eri?ata:pu2llic Ha e{//4eri?ata ereditata da Ha e pu2lic: //fun1ioni mem2ro aggiunti?e o o tituti?e protected: //fun1ioni mem2ro aggiunti?e }; La c#asse (erivata eredita da 8ase #/insieme di 5unzioni mem0ro e di varia0i#i mem0ro e accede ai mem0ri pu00#ici o protetti di 8ase' L/utente de##a c#asse (erivata accede so#o ai mem0ri pu00#ici di (erivata e 8ase- ma non ai mem0ri protetti' ./Giuseppe_N3mes1s
<31>
*unzioni o classi amic"e nella derivazione Ciascuna c#asse in una .erarchia di derivazione puo/ de5inire- secondo i consueti meccanismi previsti da #in.ua..io- 5unzioni o c#asse amiche- .arantendo ad esse tutti i diritti di accesso' 7n partico#are- una c#asse 8 puo/ de5inire amica una 5unzione mem0ro di una c#asse derivata ( oppure tutta #a c#asse (' 7n ,uesto caso ( ac,uisisce diritti comp#eti di accesso a 8- ma non puo/ trasmettere ta#i diritti a##e successive c#assi de##a .erarchi ne a.#i utenti' esempio: 6ia 8 #a c#asse 0ase- ( una c#asse (erivata contenente una 5unzione .BC' A##o scopo di consentire a .BC di accedere a##e componenti private de##a c#asse 8- essa viene de5inita amica di 8: cla e H{//cla friend 4::g(); pu2lic: ... pri?ate: ... }; e 2a e della gerarchia
cla 4:pu2lic H{//cla e deri?ata pu2lic: ?oid g();//g() puo9 accedere al dell9oggetto proprio ... }; #n esempio di gerarc"ia di derivazione
otto-oggetto 2a e
La c#asse P ;6>NA- che e/ a# c#asse piu/ .enera#e de##a .erarchia e contiene #a struttura dati atta a rappresentare un .enerico individuo e #e 5unzioni mem0ro atte a de5inire i# comportamento9 La c#asse 6EU( NE - che e/ una specia#izzazione de##a c#asse 0ase- contiene #a struttura speci5ica per rappresentare #e in5ormazioni proprie di uno studente e contiene #e 5unzioni mem0ro atte a de5inire i# comportamento speci5ico di un e#emento di ,ue##a c#asse9 La c#asse 8>;676EA-che e/ un/u#teriore specia#izzazione de##a c#asse studente e contiene a#tre in5ormazioni specia#izzate re#ative a##a c#asse stessa- piu/ speci5iche ./Giuseppe_N3mes1s
Guida C++: Aspetti Avanzati 5unzioni mem0ro che de5iniscono i# comportamento' esempio: C#asse P ;6>NA <i#e Persona'h
<32>
cla @er ona{//cla e 2a e protected: char* nome; int e o; int eta; pu2lic: //co truttore @er ona(con t char*5(.,=""Aint ),))(=1Aint ,*-=%):nome(neB charJ trlen(5(.,)=1K)A eta(,*-)A e o(),))() { trcp6(nomeA5(.,);} //generica fun1ione mem2ro ?oid chi)ei(){ cout<<")ono una per ona di nome"<<nome<<" e o"<< e o<<"eta9"<<eta<<endl; } };//fine cla e @er ona
C#asse 6tudente <i#e 6tudente'h #include "@er ona.h" cla )tudente:pu2lic @er ona{// tudente deri?ata da @er ona protected: int e ami; int matricola; char* facolta; pu2lic: //co truttore )tudente(con t char* 5(.,=""Aint ),))(=1Aint ,*-=%Aint ,)-.'=%Along .-*+'7(>-=111111Achar* "-7(>*-="") //li ta di ini1iali11a1ione che richiama il co truttore @er ona :@er ona(5(.,A),))(A,*-)A e ami(,)-.')Amatricola(.-*+'7(>-)A ./Giuseppe_N3mes1s
<33>
facolta(neB charJ trlen("-7(>*-)=1K){ trcp6(facoltaA"-7(>*-);} //fine co truttore tudente //generica fun1ione mem2ro ?oid chi)ei(){ cout<<"$n)ono uno tudente di nome"<<nome<<"i critto alla facolta9"<<facolta<<".atricola"<<matricola<<endl; } };//fine cla e tudente C#asse 8orsista <i#e 8orsista'h #include ")tudente.h" cla Hor i ta:pu2lic )tudente{//H(r i ta cla e deri?ata da tudente protected: long 2or a; pu2lic: //co truttore Hor i ta(con t char*5(.,=""Aint ),))(=1Aint ,*-=%Aint ,)-.'=%Along .-*+'7(>-=111111Achar*"-7(>*-=""Along H(+)-=1%%%%%%%) //li ta di in1iaili11a1ione richiama co truttore tudente :)tudente(5(.,A),))(A,*-A,)-.'A.-*+'7(>-A"-7(>*-)A 2or a(H(+)-){ }//fine co truttore Hor i ta //generica fun1ione mem2ro ?oid chi)ei(){ cout<<"$n)ono un ?or i ta di nome"<<nome<<"in critto alla "acolta9"<<facolta<<"ho ?into una 2or a di tudio di lire"<<2or a<<endl; } };//fine cla e Hor i ta (A N>EA; 8 N 7 (76E;UEE>;7 N>N 6>N> P; 6 NE7- "A S NG>N> ;7CH7A"AE7 7"PL7C7EA" NE N LL/>;(7N 7NS ;6> ( LLA G ;A;CH7A (7 ( ;7SAQ7>N : (A 8>;676EA A 6EU( E ' Pro.ramma Principa#e <i#e "ain'cpp #include "Hor i ta.h"//Hor i ta contiene al per ona uo interno tudente e
Guida C++: Aspetti Avanzati Hor i ta carlo("Hianchi 7arlo"A1AM#AQACP11FCA"'ngegneria"A1E%%%%%); franco.chi)ei();//richiama @er ona::chi)ei giorgia.chi)ei();//richiama )tudente::chi)ei carlo.chi)ei();//richiama Hor i ta::chi)ei }
<34>
Polimorfismo
Motivazioni per il polimorfismo 7n una .erarchia di derivazione- a#cune 5unzioni de##a c#asse 0ase sono ride5inite ne##e c#asse derivate' 6e si vuo#e con5erire #a codice #a caratteristica di dinamicita/ e di adattamento che consenta di richiamare #a 5unzione ade.uata a# tipo de##/o..etto per cui essa e/ invocata' Po#imor5ismo sta proprio ad indicare che i# so5t2are si ade.ua a##a 5orma BtipoC de##/o..etto in cui viene app#icato' Ad esempio in una .erarchia di derivazione che comprende #a c#asse 0ase <i.ura e #e c#assi derivate Punto- Cerchio- Ci#indro e si consideri una 5unzione dise.naBC diveramente de5inita per ciascuna c#asse derivata' 6ia ino#tre A un arraT di o..etti de##a c#asse <i.ura o de##e c#assi derivate- e si consideri i# se.uente cic#o: for(i=1;i<=n;i==) aJ i K.di egna(); 6i desidera natura#mente per ciascun speci5ico o..etto- richiamare #a 5unzione dise.naBC specia#izzata' A ta#e scopo percio/ occorre che sia possi0i#e determinare dinamicamente a tempo di esecuzione- #a 5unzione dise.naBC da ese.uire- in dipendenza de# tipo de##/o..etto aN i O' Ne##a pro.rammazione tradiziona#e occorre uti#izzare in ,uesto caso i# costrutto CA6 avente ,ua#e ar.omento i# tipo de##/o..etto9 ne##a pro.rammazione ad o..etti ,uesta prestazione viene 5ornita da# sistema' 7# po#imor5ismo percio/ ne##a pro.rammazione ad o..etti mi.#iora #a dinamicita/ de# sistema' 7# po#imor5ismo permette anche di mi.#iorare #/estensi0i#ita/ de# sistema- perche/ consente di a..iun.ere una nuova sottoc#asse- introducendo varianti minime a# codice esistente' 7# po#imor5ismo viene rea#izzato ne# C++ attraverso un/azione com0inatoria de# compi#atore e de# pro.ramma co##e.atore- e consiste ne# rinviare a# tempo di esecuzione #a sce#ta de##a 5unzione da richiamare: in a#tri termini- i# #e.ame tra chiamata de##a 5unzione e i# codice che #a imp#ementa e/ rinviato a tempo di esecuzione BLAE 87N(7NG- #e.ame ritardatoC' Per contrapposizione si usa i# termine #e.ame anticipato B A;LU 87N(7NGC ne# caso comune in cui #a sce#ta de##a 5unzione da richiamare viene compiuta a# tempo di compi#azione' Meccanismi sintattici per il polimorfismo 6ia 5BC una 5unzione de5inita di una c#asse 0ase de##a .erarchia e ride5inita ne##e c#assi derivate9 i# C++ consente di de5inire staticamenteBcioe/ a tempo di compi#azioneC i# #e.ame ./Giuseppe_N3mes1s
<35>
tra #a 5unzione 5BC e #/o..etto a cui deve essere app#icata B0indin. staticoC- sia di rinviare i# #e.ame a tempo di esecuzione- a##o scopo di ottenere i# po#imor5ismo' Per esprimere i# #ate 0indin. i# C++ prescrive ,uanto se.ue:
#e 5unzioni cui e/ app#ica0i#e i# #ate 0indin. devono essere speci5icatamente indicatea ta#e scopo esse devono essere individuate tramite i# ,ua#i5icatore S7;EUAL e ven.ono di conse.uenza chiamate 5unzioni virtua#i9 #a chiamata di 5unzione deve assumere una 5orma partico#are per esprimere #a richiesta di istituire e55ettivamente i# #e.ame in 5orma ritardata: ne##a chiamata de##a 5unzione 5BC #/o..etto proprio deve essere desi.nato per mezzo di un puntatore Bo di un ri5erimentoC9
7n sintesi #a notazione e/: p -! f() se.ue #a chiamata po#imor5a di 5BC- ne# senso che #a 5unzione e55ettivamente chiamata e/ ,ue##a associata a##a c#asse C cui appartiene #/o..etto c puntato da p' $ic"iarazioni delle classi della gerarc"ia cla H{ pu2lic: ?irtual ?oid f();//per f puo9 e ere e eguito il late 2inding ... }; cla 4:pu2lic H{//4eredita da H pu2lic: ?irtual ?oid f();// f() ?iene ridefinita in 4 }; Ne# pro.ramma utente si de5inisce un puntatore a##a c#asse 0ase e a esso viene asse.nato #/indirizzo di un ,ua#siasi o..etto de##a .erarchia: per attivare i# po#imor5ismo si richiama #a 5unzione virtua#e per mezzo de# punatatore: Programma utente della gerarc"ia H*p;//p punta alla cla e 2a e 4 d; // d e9 un oggetto della cla e deri?ata p=Dd; //p punta a un oggetto della cla e deri?ata p-!f(); //legame ritardatoA late 2indingA richiama la fun1ione 4::f() //u o di un arra6 di puntatori H 21A2M; 4 d1AdM; H* ppJCK={D21ADd1AD2MADdM}; for(int i=%;i<C;i==) ./Giuseppe_N3mes1s
<36>
//richiama H::f() o 4::f() in rela1ione al tipo di oggetto puntato ppJ i K-!f(); //late 2inding *unzioni virtuali pure e classi astratte 7n a#cuni casi- #a 5unzione virtua#e e/ dichiarata ma non de5inita ne##a c#asse 0ase B5unzione virtua#e PU;AC ed e/ invece de5inita ne##a c#assi derivate' La c#asse 0ase non ha a#tro che una 5unzione di inter5accia ma non e/ possi0i#e istanziare o..etti di ,uesta c#asse B#a c#asse viene detta c#asse A6E;AEEAC' Per esempio- ne#a .erarchia Persona B0aseC- 6tudente8orsista- #a 5unzione chi6eiBC de##a c#asse persona puo/ essere de5inita come virtua#e pura e conse.uentemente Persona assume i# ruo#o di c#asse astratta: cla @er ona{ ... //fun1ione mem2ro ?irtuale pura ?irtual ?oid chi)ei()=%;
}; Le successive c#assi de##a .erarchia dovranno- in ,uesto caso- de5inire #a 5unzione chi6eiBC' 7n caso contrario #a c#asse derivata eredita #a 5unzione virtua#e pura e assume anch/essa rua#o di c#asse Astratta' Costruttori e distruttori di classi polimorfe C"iamata di costruttori e distruttori Come .ia/ visto in precedenza- costruttori e distruttori non ven.ono ereditati- dun,ue ciascuna c#asse deve provvedere a##a #oro imp#ementazione' 7# #in.ua..io non consente di de5inire costruttori virtua#i: #a chiamata deve sempre avvenire con 0indin. statico- ne##/ordine de5inito da##a .erarchia di derivazione- in modo da costruire #/o..etto a partire da##a sua parte 0ase 5ino a pervenire a##a parte de5inita ne##/u#tima c#asse derivata' Per ,uanto attiene ai distruttori- essi- viceversa- possono B de00ono C essere virtua#i9 Consideriamo i# se.uente schema: 8 c#asse 0ase ( c#asse derivata- con o..etti con estensione dinamica p tipo puntatore a 8 ed i# 5rammento di pro.ramma: p=neB 4; //i tan1ia oggetto di tipo 4A con relati?a parte dinamica .... delete p; //dealloca oggetto p L/operatore ne2 richiama i# costruttore de##a c#asse ( che provvede ad istanziare #a parte dinamica9 #/operatore de#ete richiama i# distruttore per dea##ocare #a parte dinamica' 7# distruttore richiamato viene individuato a mezzo de# puntatore p a##/o..etto da ./Giuseppe_N3mes1s
<37>
dea##ocare: ne# caso di distruttore non virtua#e viene richiamato i# ditruttore de##a c#asse 8essendo p di tipo 8M- ne# caso de# distruttore virtua#e viene richiamato ,ue##o de##a c#asse ( e successivamen te ,ue##o de##a c#asse 8 Bi distruttori ven.ono richiamati a cascata: a partire da##/u#tima c#asse derivata 5ino ad arrivare a##a c#asse 0ase risa#endo a# .erarchiaC' 7n conc#usione in una .erarchia di c#assi che presentano piu/ o..etti con estensioni dinamiche occorre de5inire i re#ativi distruttori e essi devono essere virtua#i' Polimorfismo all'interno dei costruttori e distruttori (a##/interno dei costruttori e distruttori possono- in via .enera#e- essere richiamate 5unzioni mem0ro de##a .erarchia di derivazione9 in ,uesto caso #a chiamata viene sempre espressa con #e.ame anticipato' 7n a#tri termini non si puo/ app#icare i# po#imor5ismo' 7# tutto trova .iusti5icazione ne# 5atto che- in caso contrario- a mezzo di una chiamata po#imor5a potre00e essere chiamata da un costruttore una 5unzione de5inita ne##a parte 0asse de##a .erarchia- operante su un componente de##/o..etto non ancora costruito' Struttura della gerarc"ia di classi *unzioni associate alle classi A##o scopo di me.#io esaminare #e caratteristiche 5unziona#i di una .erarchia di derivazione dotata di 5unzioni mem0ro ordinate e virtua#i e/ opportuno introdurre i# concetto di <UNQ7>N " "8;> A66>C7AEA A UNA CLA66 in una .erarchia di derivazione' Considerando dun,ue una .enerica .erarchia di derivazione- con moda#ita/ di derivazione pu00#ica' Ciascuna c#asse a00ia ino#tre 5unzioni mem0ro pu00#iche' (ata una c#asse C de##a .erarchia- consideriamo #/insieme U costituito da##/unione di tutte #e c#assi che apparten.ono ai percorsi che con.iun.ono C con i# nodo radice' Possiamo dun,ue ora individuare #e 5unzioni mem0ro e #e varia0i#i mem0ro de##a c#asse C'
varia0i#i mem0ro: #a c#asse C ha per varia0i#i mem0ro #/unione de##e varia0i#i mem0ro de##a c#assi de##/insieme U9 5unzioni mem0ro: a ciascuna c#asse C sono A66>C7AE #e 5unzioni mem0ro de##/insieme U'
L/utente de##a c#asse C puo/ accedere a tutte #e 5unzioni mem0ro associate a##a c#asse C- sia che esse siano de5inite a##/interno di c#assi che precedono C #un.o #a .erarchia di derivazione' Ne# caso di >S ;;7(7NG Bcioe/ di ride5inizione di una 5unzione da parte di una c#asse derivataC- #a 5unzione mem0ro ride5inita sostituisce ,ue##a che precede ai 5ini de##a successiva .erarchia di derivazione' Percio/ con ri5erimento a C possiamo considerare #e se.uenti 5unzioni mem0ro: 5unzioni de5inite in c#assi che precedono C9 5unzioni de5inite ne##a c#asse C9 5unzioni ride5inite in C Boverriddin.C9 5unzioni ride5inite in c#assi che precedono C9
./Giuseppe_N3mes1s
Guida C++: Aspetti Avanzati Ciascuna 5unzione potra/ essere- non virtua#e- virtua#e- o virtua#e pura' Accesso alle funzioni membro della gerarc"ia
<38>
Consideriamo ora #e notazioni per #/accesso a##e 5unzioni de##a .erarchia di derivazione da parte di un utente de##a .erarchia:
#a notazione o'5BC da/ #uo.o ad un 0indin. statico e richiede dun,ue che i# #e.ame con #a 5unzione da richiamare sia de5ini0i#e a# tempo di compi#azione9 #a notazione p!L5BC e/ e,uiva#ente a##a o'5BC per #e 5unzioni non virtua#i- ne# senso che #a 5unzione richiamata viene de5inita da# compi#atore Ia partireI da##a c#asse > cui punta i# puntatore9 #a notazione p!L5BC per 5unzioni virtua#i da/ #uo.o ad un 0indin. dinamico: #a 5unzione richiamata viene de5inita Ia partireI non da##a c#asse > cui punta i# puntatore- ma da##a c#asse > primo cui appartiene #/o..etto puntato da p9 e/ in o.ni caso possi0i#e un/indicazione esp#icita de##a 5unzione da richiamare a mezzo de# nome de##a c#asse con #e notazioni: o'V::5BC oppure p!LV::5BC in ,uesto caso i# 0indin. e/ sempre statico indipendentemente da##a 5unzione'
con #a notazione o'5BC si 5a ri5erimento a una 5unzione de5inita ne##a c#asse > oppure a una c#asse che precede > ne##a .erarchia di derivazione9 con #a notazione p!L5BC si 5a ri5erimento a una 5unzione de5inita ne##a c#asse > cui punta p oppure a una c#asse che se.ue > ne##a .erarchia di derivazione: in5atti a p puo/ essere asse.nato #/indirizzo di un o..etto de##a c#asse > oppure di una c#asse derivata da >Bup!castin.C9 con #a notazione o'V::5BC oppure p!LV::5BC si puo/ richiamare una 5unzione de5inita ne##a c#asse > oppure in una c#asse che precede > #un.o #a .erarchia di derivazione9 ,uest/u#tima eventua#ita/ Bdo2n!castin.C e/ da evitare perche/ #/o..etto a cui viene app#icata #a 5BC e/ Ipiu/ picco#oI de##/o..etto proprio de##a c#asse V'
e/ dotata di un/inter5accia Bspeci5icaC e di un corpo Bimp#ementazioneC9 #a struttura dati IconcretaI di un o..etto de##a c#asse e .#i a#.oritmi che ne rea#izzano #e operazioni sono tenuti nascosti a##/interno de# modu#o che imp#ementa #a c#asse9 ./Giuseppe_N3mes1s
<39>
#o stato di un o..etto evo#ve unicamento in 0ase a##e operazioni ad esso app#icate9 #e operazioni sono uti#izzate in moda#ita/ che prescindono da##/aspetto imp#ementativo- in ta# modo e/ possi0i#e modi5icare .#i a#.oritmi senza modi5icare #/inter5accia'
e classi nel C++ 7# #in.ua..io C++ supporta esp#icitamente #a dichiarazione e #a de5inizione di tipi astratti da parte de##/utente mediante i# costrutto CLA669 #e instanze di una c#asse ven.ono dette o..etti' 7n una dichiarazione di tipo CLA66 0iso.na speci5icare sia #a struttura dati che #e operazioni consentite su di essa' Una c#asse possiede in .enera#e una sezione pu00#ica ed una privata' La sezione pu00#ica contiene tipicamente #e operazioni- dette anche metodi- consentite ad un uti#izzatore de##a c#asse' sse sono tutte e so#o #e operazioni che un utente puo/ ese.uire in maniera esp#icita od imp#icita- su.#i o..etti' La sezione privata comprende #e strutture dati e #e operazioni che si vo.#iono rendere inaccessi0i#i da##/esterno' esempio: cla 7ontatore { pu2lic : ?oid 'ncrementa(); // opera1ione incremento ?oid 4ecrementa(); // opera1ione decremento pri?ate: un igned int ?alue; // ?alore corrente con t un igned int ma8;// ?alore ma imo }; Produzione ed uso di una classe 7# meccanismo de##e c#assi e/ orientato speci5icatamente a##a riusa0i#ita/ de# so5t2are >ccorre dun,ue 5are ri5erimento ad una situazione di produzione de# so5t2are ne##a ,ua#e operano: i# produttore de##a c#asse i# ,ua#e mette a punto: #a speci5ica- in un 5i#e di intestazione Bheader 5i#eC #/imp#ementazione de##a c#asse Bun 5i#e separatoC #/uti#izzatore de##a c#asse- i# ,ua#e ha a disposizione #a speci5ica de##a c#asse- crea o..etti e #i uti#izza ne# proprio modu#o'
./Giuseppe_N3mes1s
<40>
7# modu#o utente di una data c#asse puo/ essere i# pro.ramma principa#e oppure un a#tra c#asse' Era #e due c#assi puo/ esserci una re#azione d/uso- in cui una svo#.e i# ruo#o di utente dei servizi o55erti da##/a#tra' %uolo 2cliente2 6vo#to da##a c#asse che uti#izza #e risorse messe a disposizione da##/a#tra %uolo 2Servente2 6vo#to da##a c#asse che mette a disposizione #e risorse uti#izzate da##/a#tra #so di una classe da parte di un modulo utente Un modu#o utente de##a c#asse: inc#ude #a speci5ica de##a c#asse Bcontenuta ne# 5i#e nomeC#asse'hC de5inisce o..etti istanze de##a c#asse e invoca i metodi su.#i o..etti Istanziazione degli oggetti Un o..etto e/ un/istanza esemp#are de##a c#asse' (ue esemp#ari de##a stessa c#asse sono distin.ui0i#i so#tanto per i# #oro stato- sono i va#ori dei dati mem0ro- mentre i# comportamento potenzia#e e/ identico' #so di una classe a specifica di una classe ;appresenta un/inter5accia per #a c#asse stessa in cui sono descritte: #e risorse messe a disposizione ai suoi potenzia#i utenti #e re.o#e sintattiche per i# #oro uti#izzo / separata da##a imp#ementazione- permette #/uti#izzo senza che .#i utenti conoscano i detta.#i de##a imp#ementazione' / a cura de##o svi#uppatore de##a c#asse' / scritta in un apposito 5i#e di intestazione' esempio: 6P C7<7CA ( LLA CLA66 / / nome del file 7.h cla 7 { pu2lic: //prototipi delle fun1ioni mem2ro ./Giuseppe_N3mes1s
Guida C++: Aspetti Avanzati *1 f1( ....) ; *M fM( ....) ; pri?ate: // truttura dati interna int i; char c; } ; //fine pecifica della cla 'implementazione di una classe
<41>
e 7.
/ #a codi5ica in C++ de##e sin.o#e operazioni presentate ne##/inter5accia de##a c#asse' / una partico#are so#uzione- perche/ puo/ cam0iare #/imp#ementazione senza che cam0i #/inter5accia' / a cura de##o svi#uppatore de##a c#asse' / scritta in un apposito 5i#e di imp#ementazione Bestensione 'cppC esempio: //implementa1ione della cla e //nome del file 7.cpp #include "7.h" *1 7::f1(...){ //reali11a1ione della fun1ione f1 } *M 7::fM(...){ //reali11a1ione della fun1ione fM } //fine del file 7.cpp Struttura degli oggetti Ciascuno o..etti- che e/ istanza di una c#asse- e/ costituito:
da una parte 0ase- a##ocata per e55etto de##a de5inizione de##/o..etto ne# pro.ramma utente in un area di dati statici- ne##/area stac% o ne##/area heap- in 0ase a##e c#assi di memorizzazione9 da una eventua#e estensione- a##ocata in un area heap'
Guida C++: Aspetti Avanzati dea##ocazione de5inizione de##/o..etto: a cura de# pro.ramma utente a##ocazione parte 0ase: a cura de# compi#atore
<42>
a##ocazione eventua#e estensione: mediante una specia#e 5unzione mem0ro detta C>6E;UEE>; Ba cura percio/ de# produttore de##a c#asseC inizia#izzazione o..etto: a cura de# costruttore dea##ocazione eventua#e estensione: a cura di una specia#e 5unzione mem0ro detta (76E;UEE>; dea##ocazione parte 0ase: a cura de# compi#atore
Costruttori 7# costruttore e/ una 5unzione mem0ro: che ha #o stesso nome de##a c#asse non restituisce nessuno risu#tatoBnemmeno voidC Invocazione dei costruttori >.ni istanziazione di un o..etto de##a c#asse produce #/invocazione di un costruttore #/o..etto e/ creato come varia0i#e .#o0a#e o #oca#e: -ccount act(1%%); #/o..etto e/ creato come varia0i#e dinamica: -ccount *act = neB -ccount(1%%); 6e i# compi#atore non individua i# costruttore da chiamare produce un errore' 6e #/o..etto ha dei dati mem0ro di tipo c#asse- su ciascuno di essi e/ chiamato ricorsivamete i# costruttore ciascuno dei dati mem0ri sono chaimati secondo #/ordine di dichiarazione dei dati #a chiamata dei costruttori dei dati mem0ro precede #a chiamata de# costruttore de##/o..etto esempio: Pro.ramma utente de##a c#asse C #include "account.h" main(){ //-lloca1ione di un oggetto -ccount act(1%%);//?iene in?ocato il co truttore ./Giuseppe_N3mes1s
<43>
//act e9 una ?aria2ile automatica che ?iene allocata nell9area tacR //alloca1ione dinamica di un oggetto -ccount *pact= neB -ccount(1%%);//in?oca il co truttore //il puntatore pact e9 una ?aria2ile automatica allocata in area tacR; //l9oggetto puntato e9 allocato in area heap; }//fine programma utente $istruttori 7# distruttore e/ una 5unzione mem0ro che: e/ necessaria so#o se #/o..etto presenta un/estensione dinamica ha #o stesso nome de##a c#asse preceduto da WBti#deC non restituisce nessun va#ore Bnemmeno voidC ne/ ha a#cun parametro ha #o scopo di dea##ocare #/estensione dinamica di un o..etto non puo/ essere invocato esp#icitamente da# pro.ramma utete- ma viene invocato imp#icitamente da# compi#atore ,uando termina i# cic#o di vita di un o..etto Invocazione dei distruttori 6e una c#asse 5ornisce un distruttore- ,uesto/ e/ automaticamente chiamatao on.i vo#ta che un o..etto de##a c#asse deve essere dea##ocato: #/o..etto e/ #oca#e e si esce da# 0#occo in cui e/ stato dichiarato #/o..etto e/ ne##o heap e su di esso viene ese.uito un ( L E #/o..etto e/ dato mem0ro di un a#tro o..etto e ,uest/u#timo viene dea##ocato in ,uesto caso: i distruttori dei dati mem0ri ven.ono invocati ne##/ordine di dichiarazione dei dati #a chiamata dei distruttori dei dati mem0ri se.uono #a chiamata de# distruttore de##/o..etto 6e una c#asse non 5ornisce un distruttore ne viene creato uno di de5au#t che invoca ordinatamente i distruttori di tutti i dati mem0ro' esempio: //programma utenta della cla e 7 #include "account.h" ?oid f(){ //-lloca1ione dinamica di un oggetto -ccount *pact=neB -ccount(1%%); if(...){ -ccount act(1%%);//in?oca il co truttore ... //fine del 2loccoA ?iene in?ocato il di truttoreA e act ?iene deallocato dall9area tacR } ./Giuseppe_N3mes1s
Guida C++: Aspetti Avanzati delete pact;//?ieni in?ocato il di truttore per l9area heap puntata da pact }//fine procedura f &ipi di costruttori
<44>
esempio: // pecifica della cla e //nome del file 7.h cla 7{ pu2lic: //fun1ioni co truttore 7();//co truttore a 1ero argomenti 7(?alori ini1iali);//co truttore con piu9 argomenti 7(con t 7D c1);//co truttore di copia pri?ate: // truttura dati }//fine della pecifica della cla e 7 e funzioni membro I3 I30 Le 5unzioni mem0ri in#ine posso essere de5inite in uno dei se.uenti due modi: usando #a paro#a chiave in#ine ne##a de5inizione de##a 5unzione mem0ro senza #a paro#a chiave in#ine ma inserendo i# corpo de##a 5unzione ne##a stessa inter5accia de##a c#asse I dati membro S&A&IC 7 dati mem0ro- pu00#ici o privati- di una c#asse posso essere dichiarati static' 6ono dati creati ed inizia#izzati una so#a vo#ta- indipendentemente da# numero di o..etti istanziati: vanno dichiarati ne##a de5inizione de##a c#asse e de5initi ed imp#ementate separatamente usando #/operatore di riso#uzione de##o scope- i dati pu00#ici- come #e norma#i varia0i#i .#o0a#i- possono essere usati dovun,ue ne# pro.ramma e funzioni membro S&A&IC Le 5unzioni mem0ro- pu00#iche o private- di una c#asse posso essere dichiarate static'
./Giuseppe_N3mes1s
Guida C++: Aspetti Avanzati 6ono 5unzioni che non ricevono #/ar.omento EH76 e ,uindi: possono accedere so#o ai dati mem0ro statici de##a c#asse possono invocare so#o 5unzioni mem0ro statiche de##a c#asse e funzioni membro C-3S&
<45>
Le 5unzioni mem0ro che non vanno a modi5icare #/o..etto devono essere esp#icitamente dichiarate const' La paro#a chiave C>N6E se.ue #a #ista de.#i ar.omenti e deve essere presente sia ne# prototipo de##a 5unzione mem0ro che ne##a de5inizione' ,li oggetti C-3S& Lu 5unzioni mem0ro const sono #e uniche che possono essere chiamate su un o..etto const Ba parte i costruttori ed i distruttoriC Il costruttore di C-PIA 7# costruttore di copia di una c#asse C ha #a 5orma: 7(con t 7D) Siene uti#izzato ,uando si deve rea#izzare #a copia di un o..etto esistente: ne# creare un c#one di un o..etto ne# passare #/o..etto per va#ore ne# restituire #/o..etto per va#ore Copia superficiale e copia profonda Guando #a c#asse non 5ornisce un costruttore di copia- i# compi#atore ne crea uno di de5au#t che e55ettua #a copia super5icia#e de##/o..ettoBIsha##o2 copTIC' Consiste ne##/app#icare ordinatamente i# costruttore di copia ad o.ni dato mem0ro Bper i dati re#ativi #a copia avviene con #/operazione sui primi 0Tte re#ativiC Guando tra i dati mem0ri de##/o..etto vi son puntatori- non e/ opportuno usare #a copia super5icia#e ma 0ensi/ una copia pro5onda BIdeep copTIC' 7n ,uesto caso i# costruttore di copia deve essere esp#icitamente pro.rammato' Ne# caso de##o sha##o2 copT: 7 caratteri di due strin.he sono condivisi BIsharin.IC modi5icando i# carattere di una strin.a si modi5ica anche #/a#tra strin.a se una de##e due strin.he e/ dea##ocata- i# distruttore dea##oca anche #/arraT di caratteri- #asciando cosi/ #a/tra strin.a in uno stato scorretto- con un puntatore Idan.#in.I'
./Giuseppe_N3mes1s
Guida C++: Aspetti Avanzati Ne# caso de# deep copT: >.ni strin.a ha #a sua copia di caratteri ,ua#un,ue operazione su una strin.a non modi5ichera/ #/a#tra' 'operatore di assegnazione L/operatore di asse.nazione di una c#asse C ha #a se.uente 5orma: 7D operator=(con t 7D); La sua imp#ementazione di55erisce da ,ue##a de# costruttore di copia: deve veri5icare che non si tratti di un autoasse.nazione BFKFC deve distru..ere #/o..etto va#ore attua#e de##a varia0i#e a cui si asse.na deve restituire i# ri5erimento a##a varia0i#e stessa per permettere catene di asse.nazione BFKTKzC'
<46>
Puntatori in C++
7# C++ prevede puntatori a 5unzioni e puntatori a dati di tutti i tipi- semp#ici o strutturati' &ipo puntatore / un tipo che puo/ assumere come insieme di va#ori tutti .#i indirizzi di memoria' Un puntatore ad una varia0i#e di tipo E identi5ica #/indirizzo di memoria de##a varia0i#e' Percio/ una varia0i#e di tipo puntatore e/ una varia0i#e che contiene #/indirizzo di memoria de##a varia0i#e puntata' t6pedef int * pint; pint pcount; //?aria2ile di tipo puntatore int count=1%; pcount=Dcount; // al puntatore ?iene a egnato l9indiri11o della ?aria2ile count *pint //denota la ?aria2ile puntata da pint (deferen1ia1ione) sempio: int main() { int i=1%; int* p=Di; //@ contiene l9indiri11o di n *p=M%; return %; } ./Giuseppe_N3mes1s
<47>
La dimensione de# puntatore Bsizeo5BCC e/ costante ed e/ indipendente da# tipo puntatone##/architettura a 3* 0it e/ di A 0Tte' Inizializzazione dei Puntatori Un puntatore non inizia#izzato- come ,ua#siasi varia0i#e- ha come va#ore inizia#e uno a#eatorio B va#ore de# re.istro di memoria a##/atto de##a sua de5inizione C' / imporatente dun,ue inizia#izzare #a varia0i#e' Un puntatore che viene inizia#izzato a ) BzeroC o a NULL non ha nessun va#ore- non punta ad nessun o..etto e ,uindi non indirizza a nessun dato presente in memoria ed e/ detto puntatore nu##o' sempio: char *p=%; //oppure char *p=53>>; // i puS te tare il ?alore del puntatore if (p==%) ... //oppure if (p==53>>) Puntatore a puntatore int i=1%%; int *ptr1=Di; int **ptrM=Dptr1 ptr1 e ptr* sono due puntatori diversi' 7# primo X un puntatore ad un intero' 7# secondo- invece- X un puntatore a puntatore' i= QE; *ptr1=QE; **ptrM=QE; Puntatori costanti Un puntatore costante ha un va#ore che non puo/ essere cam0iato: ** con t p= <indiri11o ?ar!; esempio: int *con t p1=D8; p1 e/ un puntatore constante che punta a F- p1 e/ constante e ,uindi non puo/ essere modi5icato i# suo ri5erimento- ma Mp cioe/ F e/ una varia0i#e a cui possiamo invece modi5icare i# va#ore' ./Giuseppe_N3mes1s
Guida C++: Aspetti Avanzati *p1=1%;//(; p1=D6;//,++(+, Puntatori a costanti con t ** p= <indiri11o con t o tringa!;
<48>
/ un puntatore ad una varia0i#e constante- const' 7# va#ore de# puntatore si puo/ modi5icare mentre i# va#ore puntato no' con t int 8=ME; cont int *p1=D8; *p1= De; //(;A 0ualun0ue tentati?o di modificare il ?alore di e comportera un errore di compila1ione *p1=1E; //,++(+, Puntatori constanti a costanti con t ** con t p= <indiri11o con t o con t int 8=ME; con t int * con t p1=D8; Gua#siasi tentativo di modi5icare p1 o Mp1 produrra/ un errore di compi#azione' I puntatori+ -perazioni 7# c++ tratta esp#icitamente #e espressioni di tipo puntatore' 6ono previste #e se.uenti operazioni:
tringa!;
A66 GNAQ7>N : tra puntatori che punatano a##o stesso tipo EM: >peratori unari unitari B5orma pre5issa e post5issaC 7NC; " NE>: I++I ( C; " NE>: I!!I 6>"" (7<< ; NQA: tra un puntatore ed un intero
Puntatori a dati strutturati Un puntatore puo/ puntare a tipo di dati strutturati B arraT o record C' 6i ana#izzeranno i se.uenti casi:
./Giuseppe_N3mes1s
<49>
Puntatore ad arraT9 //puY uti#mente essere sostituito da##a notazione a N i O tipica de.#i arraT Puntatore a record9
Puntatore ad arra4 7# puntatore ad arraT e/ una varia0i#e che punta a##a prima #ocazione de##/arraT BaN)O in C+ +C9 Considerando pero/ che .#i e#ementi sono tutti in posizioni conti.ue- i# puntatore puntera/ a tutti .#i e#emetni de##/arraT' Un puntatore ad arraT e/ dun,ue di per se un puntatore costante a# tipo E de.#i e#ementi de##/arraT' sempio: con t int dim=1%%; float a JdimK; // a T un arra6 di dim elementi di tipo float float* p ; // p T un puntatore a float //a11eramento di tutti gli elementi di un arra6 di 1%% elementi for (p = aA int i=%; i<dim; i==A p==) *p= %; Puntatore a record Un puntatore a record e/ una varia0i#e che punta a##/indirizzo di memoria ove e/ a##ocato i# record- ,uesto e/ mot#o uti#e ne##a rea#izzazione di tipi dinamici' sempio: // 4ichiara1ioni di un tipo trutturato * truct * { // * T un tipo trutturato 41; .....; 4n ; } ; * r ; // r T ?aria2ile di tipo * // 4ichiara1ione di un tipo puntatore a * t6pedef * * @unt; // 4ichiara1ione di ?aria2ile di tipo puntatore a * @unt p; @unt p = Dr; // p e9 una ?aria2ile puntatore ini1iali11ata ad r p puo9 e ere ridefinito nel cor o del programma
p= Dr1; //ora p punta alla ?aria2ile r1 di tipo * Accesso a##a sin.o#a componente: ./Giuseppe_N3mes1s
Guida C++: Aspetti Avanzati (*p).4i; p-!4i; sempio: // 4efini1ione di tipo truttura: truct -22onati { // defini ce truttura di nome -22onati )tringa nominati?o; )tringa indiri11o; int num*el ; }; t6pedef -22onati* @a22; // 4efini1ione di ?aria2ili -22onati a; // a una ?aria2ile di tipo -22onati @a22 p= Da; // pA di tipo @a22A e9 ini1iali11ato ad a // -cce o alla componente nominati?o mediante puntatore p-!nominati?o;
<50>
Guida C++: Aspetti Avanzati Le de5inizioni non possono essere ripetute' Le dichiarazioni devono essere consistenti tra #oro e con #e de5inizioni'
<51>
esempi di dichiarazioni: e8tern int a; // dichiara(ma non defin.) la ?aria2le aA definita in altro file. truct @er ona; // dichiara un nome di tipo per una truct. ?oid f(int); // dichiara(ma non defin.) la fun1ione f (prototipa1ione). esempi di de5inizione: con t int 2 = E; // defin. di co tante con nome int a; // defin. di ?aria2ile truct @er ona { // defini ce il tipo @er ona char 5omeJM%K; } ; ?oid f(int 8) { // defini1ione di fun1ione } // corpo della fun1ione Classi di memorizzazione delle variabili nel C++ Per #e varia0i#i in C++- #a de5inizione speci5ica #a c#asse di memorizzazione- cioe/: #a visi0i#ita/ spazia#e9 #a durata tempora#e Bcic#o di vitaC9 #/a##ocazione in memoria durante #/esecuzione' C#assi di memorizzazione de# C++ Bstora.e c#assC: varia0i#i automatiche varia0i#i esterne varia0i#i automatiche statiche varia0i#i esterne statiche varia0i#i re.istrer varia0i#i dinamiche Modello di gestione della memoria per l'esecuzione di un processo
Area pro.rammi e costanti destinata a contenere #e instruzioni- in #in.ua..io macchina- e #e costanti de# pro.ramma Area dati statici destinata a contenere varia0i#i a##ocate staticamente e ,ue##e esterne B.#o0a#iC Area heap destinata a contenere #e varia0i#i dinamiche esp#icite- di dimensioni non prevedi0i#i a tempo di compi#azione Area stac% destinata a contenere #e varia0i#i automatiche ,ue##e de5inite a##/interno de##e 5unzioni
./Giuseppe_N3mes1s
Guida C++: Aspetti Avanzati 1ariabili automatic"e 6ono #e varia0i#i #oca#i ad un 0#occo di istruzioni' 6ono de5inite in un 0#occo di istruzioni e sono a##ocate e dea##ocate con esso' La visi0i#ita/ #essica#e e/ #oca#e a# 0#occo' 7n memoria sono a##ocate ne##/area stac%' 1ariabili esterne
<52>
6ono #e varia0i#i che ven.ono de5inite a##/esterno di o.ni 0#occo' La visi0i#ita/ #essica#e si estende a tutto i# pro.ramma- me per render#e visi0i#i anche a##e procedure contenute in 5i#e diversi- devono essere ivi dichiarate con #a paro#a chiave eFtern' La #oro estensione tempora#e si estende a tutto i# pro.ramma' 7n memoria ven.ono a##ocate ne##/area dati statici o .#o0a#e' 1ariabili automatic"e static"e 6ono varia0i#i automatiche pre5issate con #a paro#e chiave static' La visi0i#ita/ #essica#e e/ #oca#e a# 0#occo di istruzioni dove sono de5inite' La #oro estensione tempora#e si estende a tutto i# pro.ramma' 7n memoria ven.ono a##ocate n##/area dati .#o0a#e' 1ariabili esterne static"e 6ono varia0i#i esterne pre5issate con #a pao#a chiave static' La visi0i#ita/ #essica#e e/ #oca#e a# 5i#e dove sono dichiarate' La #oro estensione tempora#e si estende a tutto i# pro.ramma' 7n memoria ven.ono a##ocate n##/area dati .#o0a#e' 1ariabili register 6ono varia0i#i automatiche pre5issate con #a paro#a chiave re.ister' La visi0i#ita/ #essica#e e/ #oca#e a# 0#occo dove sono dichiarate' 6ono a##ocate e dea##ocate con i# 0#occo di istruzioni in cui esse sono contenute' 6e possi0i#e ven.ono a##ocate in un re.istro de# processore- a#trimenti ne##/area stac%' Puo/ convenire dichiarare re.ister una varia0i#e automatica usata di 5re,uente- in modo che #/a##ocazione in un re.istro de##a macchina ne aumenti #a ve#ocita/ di accesso' 1ariabili dinamic"e 6ono de5inite durante #/esecuzione de# pro.ramma mediante puntatori' 6ono accessi0i#i ovun,ue esiste un ri5erimento ad esse' L/a##ocazione e #a dea##ocazione sono contro##ate da# pro.rammatore' ./Giuseppe_N3mes1s
Guida C++: Aspetti Avanzati 7n memoria ven.ono a##ocate ne##/area heap' 1ariabili e strutture dinamic"e La .estine de##e varia0i#i dinamiche e/ a cura de# pro.rammatore- attraverso dei meccanismi #un.uistici che sono:
<53>
-peratore 305 7n 5ase di esecuzione- #/operatore ne2 a##oca un/area atta ad ospitare un va#ore di tipo E e restituisce i# puntatore a ta#e area9 7# tipo E de5inisce imp#icitamete #/area di memoria occorrente' esempio: ** re ** re p = neB *; //alloca area atta a contenere un elemento e titui ce puntatore p1 =neB *JnK; //alloca area atta a contenere n elementi e titui ce puntatore
-peratore $0 0&0 Produce #a dea##ocazione de##/area di memoria punatata da una varia0i#e p- cioe/ annu##a #/a##ocazione- rendendone di nuovo disponi0i#e #o spazio de memoria ne##/area heap' esempio: delete p; //dealloca area puntata da p delete JK p1; //dealloca tutto l9arra6 precedentemente allocato delete J1%K p1; //dealloca 1% elementi a partire da 0uello puntato da p1 Allocazione dinamica di un arra4 Con #/a##ocazione dinamica di un arraT i# puntatore restituito e/ ,ue##o de##/indirizzo de# primo e#emento de##/arraT' float* a= neB floatJnK; 7# ri5erimento a.#i e#ementi de##/arraT viene espresso a mezzo de##a consueta notazione con indice
./Giuseppe_N3mes1s
<54>
Allocazione dinamica di un record L/a##ocazione dinamica di un record avviene ana#o.amente- attraverso #/uso de##/operatore ne2' 7ndicanro con ; un tipo di record e con r un puntatore ad ;- si ha: +* r = neB +; Allocazione dinamica di un record contenente un puntatore // 4efini1ione di tipo truttura: truct -22onati { // defini1ione del record -22onati char* nominati?o; )tringaF% indiri11o; int num*el ;} ; //alloca1ione dinamica di un record di tipo -22onati -22onati* p = neB -22onati; //legge nominati?o da ta tiera char nomeJE%K; cin.get(nomeAE%); p-!nominati?o = neB charJ trlen(nome ) = 1 K; trcp6(p-!nominati?oA nome); cout << p-! nominati?o; // dealloca1ione delete JKp-!nominati?o; //nece ario < delete p; Collegamento fra record generati dinamicamente truct -22onati; t6pedef -22onati* @a22; // 4efini1ione di tipo truttura: truct -22onati { // defini1ione del record -22onati char * nominati?o; )tringaF% indiri11o; int num*el ; @a22 ucc;//punta al ucce i?o record } ; //4efini1ione di due ?aria2ili di tipo puntatore ad -22onati @a22 pA p1; //-lloca1ione di due ?aria2ili di tipo -22onati p = neB -22onati; p1= neB -22onati; //7ollegamento del primo record con il econdo p-! ucc=p1;
./Giuseppe_N3mes1s
<55>
//@er generare dinamicamente piU record collegati a me11o di una catena di puntatoriA V ufficiente ini1iali11are olo il primo recordAcon le i tru1ioni p = neB -22onati; 0 = p; // il ?alore di p non de?e e ere alteratoA V la te ta della catena ed effettuare 0uindi in ciclo le opera1ioni 0 -! ucc = neB -22onati 0 = 0-! ucc;//a?an1a lungo la truttura 0rrori comuni con puntatori e variabili dinamic"e Eipici errori ,uando si usano varia0i#i dinamiche sono: (imenticare di a##ocare un dato ne##o heap e usare i# puntatore come se #o stesse ri5erendo (imenticare di restituire #a memoria uti#izzata a##o heap mana.er BmemorT #ea%C Eentare di usare dati dinamici dopo che sono stati restituiti a##o heap mana.er 7nvocare de#ete piu/ di una vo#ta su##o stesso dato
tatic&ca t<*! (8) ! converte F a# tipo E- per tipi co##e.ati tra #oro' reinterpret&ca t<*! (8) ! converte F ne# tipo E- per tipi N>N co##e.ati tra #oro d6namic&ca t<**! (p) ! converte p a# tipo EM- per c#assi di una .erarchia con t&ca t<*! (8) ! consente di a#terare #/o..etto costante F di tipo E ./Giuseppe_N3mes1s
Guida C++: Aspetti Avanzati static6cast 6i uti#izza per tipo co##e.ato tra #oro- #a veri5ica e/ ese.uita a tempo di compi#azione' esempio: dou2le 1=F.1CECC int i= tatic&ca t<int!(1);
<56>
6i uti#izza spesso per #a conversione di tipi aritmetici- tra puntatori a void e puntatori a# tipo E e in .enera#e per tutte ,ue##e operazioni di conversioni #ecite cioe/ che esiste a#meno un cammino di conversione tra i# tipo di F ed i# tipo E' reinterpret6cast 6i uti#izza per tipi N>N co##e.ati tra #oro' esempio: char* tr="a2c"; int i= reinterpret&ca t<int!( tr); 7# risu#tato cui si perviene attraverso ,uesto castin. non e/ tipicamente porta0i#e da un sistema a##/a#tro' d4namic6cast 6i uti#izza per ese.uire cats dinamica tra puntatori' d6namic&ca t<**! (p); restituisce ) se p non punta ad un o..etto di tipo E restituisce p se p punta ad un o..etto di tipo E- oppure ad una c#asse accessi0i#e da E L/operatore in esame e/ uti#izzato in .enere per una conversione di tipo a tempo di esecuzione per i# do2n!castin. di puntatori Bda puntatore di una c#asse 0ase a uno di una c#asse derivataC const6cast 6i uti#izza per convertire un o..etto costante in un o..etto non costante' con t&ca t<*! (8); a#tera #a constness de##/o..etto costane F di tipo E
./Giuseppe_N3mes1s
Guida C++: Aspetti Avanzati Conversione di tipo per oggetti di tipo classe La conversione di tipo per varia0i#i di tipo c#asse e/ ese.uita nei se.uenti casi: ne##/operatore di asse.nazione con o..etti di tipo diverso ne##a chiamata de##e 5unzioni- se parametro e55ettivo e parametro 5orma#e sono scam0iati per va#ore e sono di tipo diverso Conversione mediante costruttori Una 5unzione costruttore de##a c#asse V de# tipo: W(7D); Puo/ essere ri.uardata come un operatore di conversione C!LV' sse e/ richiamata imp#icitamente da# compi#atore per ese.uire #/operazione di conversione' 7# tipo C puo/ essere di tipo standard oppure de5inito da##/utente'
<57>
Gua#ora si vo.#ia ini0ire #/uti#izzo de# costruttore per #e operazioni imp#icite di conversione di tipo 0iso.na premettere #/attri0uto eFp#icit VBCPC' La conversione di tipo C!LV e55ettuata mediante costruttore non e/ possi0i#e: se V e/ un tipo prede5inito se V e/ una c#asse .ia/ esistente che non dispone de# costruttore VBCPC Per ta#e motivo i# C++ introduce .#i operatori di conversione: operator VBC9//converte o..etto proprio a##a c#asse V esempio: )tringa{ operator int(); }; )tringa::operator int(){ //tra forma oggetto proprio di tipo )tringa in un intero return i; } )tringa ("1MF"); int i= ; //richiama .operator int();
Guida C++: Aspetti Avanzati cC= (c1=cM)*cF con c1- c*- c3- cA varia0i#i di tipo numero comp#esso' 7n rea#ta/- un/operazione su tipo prede5inito- come ad esempio: i1=iM // omma di due interi
<58>
puo/ essere ri.uardata come ese.uita a mezzo di richiamo di una 5unzione che ese.ue #/operazione richiesta- svi#uppano un a#.oritmo noto a# compi#atore' La 5unzione somma e/ ino#tre ride5inita ne# #in.ua..io C++ perche/ e/ anche prevista #a somma di due rea#i: r1=rM // omma di due reali ( ridefini1ione della fun1iona omma)
L/operazione in esame e/ rea#izzata con un a#.oritmo diverso- anch/esso noto a# compi#atore' La 5unzione somma puo/ essere u#teriormente ride5inita- con ri5erimento ad operandi appartenenti a una c#asse C: c1=cM // omma di due oggetti della cla e 7
L/operazione viene in ,uesto caso ese.uita secondo un a#.oritmo de5inito da# pro.ettista de##a c#asse C' (a# punto di vista tecnico- #a redi5inizione di un .enerico operatore >P viene rea#izzata mediante de5inizione di una 5unzione di nome operator op' L/occorrenza de##/operatore op in un/istruzione produce #/attivazione de##a 5unzione operator op in precedenza de5inita' Cosi/ app#icato #a 5unzione: c1=cM viene tras5ormata in: c1.operator op(cM) che produce #/attivazione de##a 5unzione operator opBC de##a c#asse C' 6i tratta de##a de5inizioni di piu/ 5unzioni operator opBC che costituiscono dun,ue un insieme di 5unzioni di e.ua# nome sovraccaricate Boperator over#oadin.C' 7# compi#atorecome per i# sovraccarico dei nome- sce.#iera/ #a 5unzione che ma..iormente si adatta a# tipo de.#i operandi' #na tassonomia degli operatori G#i operatori posso essere c#assi5icati cosi/:
unari Baccettano un so#o operandoC pre5issiB#/operatore precede #/operandoC esempio ne2 e de#ete post5issiB#/operatore se.ue #/operandoC ./Giuseppe_N3mes1s
<59>
A#cuni operatori possono essere sia unari che 0inari ad esempio M Bdere5erenziazione- mo#tip#icazioneC A#cuni operatori possono essere sia pre5issi che post5issi ad esempio ++ e !! e regole da seguire Per introdurre un operatore 0iso.na se.uire de##e re.o#e:
e/ possi0i#e modi5icare i# si.ni5icato di un operatore esistente- non e/ possi0i#e creare nuovi operatori- non e/ opportuno cam0iare #a semantica di operatori app#icati a tipi de5initi9 non e/ possi0i#e cam0iare precedenza- associativita/ e IaritTIBnumermo di operandiC9 non e/ possi0i#e usare ar.omenti di de5au#t'
come 5unzione mem0ro di una c#asse un operatore 0inario ha un so#o parametro- mentre un operatore unario non ha parametriB#/a#tro operando e/ #/o..etto a cui si app#ica #/operatoreC come 5unzione non mem0ro ,uesta so#uzione e/ o00#i.atoria ,uando #a c#asse non e/ disponi0i#e'
Come si comporta il compilatore 7# compi#atore ,uando incontra un/espressione de##a 5orma: 8 op 6 veri5ica ne##/ordine:
se ne##a c#asse V de##/o..etto F vi e/ una 5unzione mem0ro de##a 5orma operator opBUC- dove U e/ #a c#asse de##/o..etto T se vi e/ una 5unzione non mem0ro de##a 5orma Ioperator opBV-UCI
e provvede ad invocare #a 5unzione individuata' ,li operatori 2sovraccaricabili2 7# C++ consente di ride5inire ,uasi tutti .#i operatori previsti de# #in.ua..io: = * / X Y D Z ./Giuseppe_N3mes1s
Guida C++: Aspetti Avanzati [ < A = < ! <= == -- << !! == <= DD == -= *= /= X= Y= D= <<= !!= JK () -! -!* neBJK deleteJK != ZZ Z= neB delete
<60>
A#cuni operatori posso essere sovraccaricati so#o come 5unzioni mem0ro: = JK () -! Per a#tri .#i a#tri se.uiamo #a se.uente 5orma: >peratore >peratre unario +K ZK /K MK [K PK \K ]K LLK ^^K >.ni a#tro operatore 0inario %idefinizione di operatori specifici >ra andremo a vedere piu/ ne##o speci5ico #a ride5inizione dei vari operatori:
operatore di asse.nazione9 operatori di incremento e decremento9 operatori di indicizzazione9 operatore P9 operatore vir.o#a9 operatore di chiamata di 5unzione9 operatore 39 operatore di shi5t ^^ e LL9 operatore !L9 operatore NO con dimensioni mu#tip#e9 operatori ne2 e de#ete9 operatori di conversione'
-peratore di assegnazione Prendiamo come esempio una c#asse C e con c e c1 due o..etti a caso di ta#e c#asse#/operatore di asse.nazione rea#izza operazioni de##a 5orma cKc1 ed e/ dun,ue un operatore 0inario che ha i# compito di produrre #/asse.nazione de##e componenti di c1 a##e ana#o.he componenti di c' Guesto operatore deve essere ride5inito ne# caso in cui .#i o..etti si presentano con estensione dinamica- andremo ad operare cosi/:
./Giuseppe_N3mes1s
<61>
ricopiare #a parte 0ase de##/o..etto c1 ne##a parte 0ase de##/o..etto c- a eccezione de# puntatore a##/estensione dinamica9 dea##ocare #/estensione di c in area heap9 a##ocare una nuova estensione di c in area heap9 ricopiare #/estensione di c1 ne##/estensione di c'
(a# punto di vista sintattico i# prototipo ha #a 5orma: 7D operator=(con t 7D c1); 7# va#ore restituito e/ un ri5erimento a##/o..etto proprio- e in ,uesto modo ven.ono consentite #e asse.nazioni mu#tip#e- ne##a 5orma c*KcKc1' -peratori di incremento e decremento L/operatore ++ puo/ assumere come e/ noto- 5orma pre5issa e post 5issa' Per distin.ure #a 5unzione operator ++BC nei due casi- i# compi#atore consente di de5inire due distinte 5unzioni sovrapposte: ++ pre5isso: prototipo 7 operator ==(); // chiamata ==c ++ post5isso: prototipo 7 operator ==(int); //chiamata c== 7# compi#atore tras5orma #a notazione c++ in c'operator++B)C' Ana#o.amente posso essere de5initi .#i operatori !! post5issi e pre5issi' -peratori di indicizzazione Un impie.o tipico de##/operatore di indicizzazione e/ ,ue##o #e.ato a##a c#asse Settore- che prevede #/accesso a.#i e#ementi di un vettore con contro##o de##/indice- a##o scopo di veri5icare che esso non sia esterno a##/interva##o No-dim!1O' Ciascun o..etto a di tipo Settore e/ costituito da##e componenti dim- dimensione de# vettore- e v- puntatore a##/area contenente i# vettore' La 5unzione operatorNO viene de5inita: *D operatorJK(int i){ //controlla i ri petto ai limiti del ?ettore return ?JiK;//re titui ce riferimento a elemento i-e imo } La 5unzione in esame e/ richiamata con notazioni de##a 5orma aNiO- uti#izza0i#i sia per accesso ad aNiO sia per a..iornamento' Gua#ora occore 5ar ri5erimento a.#i e#ementi di aNiO di un vettore costante non e/ necessario de5inire una seconda 5unzione operatorNO' La 5unzione avra/ prototipo cosi/:
./Giuseppe_N3mes1s
<62>
7n a#tre paro#e- ne# caso siano de5inite entram0i #e 5unzioni- ,ue##a con o..etto proprio non const verra/ richiamata per vettori non const e consentira/ operazioni di a..iornamento,ue##a con o..etto proprio const verra/ richiata per vettori const' -peratore 7 L/operatore P e/ un operatore prede5inito per #e varia0i#i di tipo c#asse: Pc 5ornisce #/indirizzo de##/o..etto c' Ne# caso di o..etto a di tipo Settore #/operatore P puo/ essere ride5inito- a##o scopo di ottenere non #/indirizzo de##/o..etto- ma piuttosto #/indirizzo inizia#e de##/area v: con t ** operatorD()con t{//re titui ce indiri11o ini1iale del ?ettore return ?; } -peratore virgola L/operatore vir.o#a e/- in .enera#e- usato per espressioni de##a 5orma e-e1 e produce i# ca#co#o di e ed e1 restituendo e1' 6e e ed e1 con .#i o..etti c e c1 de##a c#asse C- #/operatore vir.o#a puo/ essere ride5inito ne##a 5orma: 7 operatorA(7D c1); La 5unzione in esame puo/ essere uti#izzata per ese.uire ,ua#che e#a0orazione su##/o..etto proprio c e su c1 per restituire i# va#ore c1' -peratore di c"iamata a funzione L/operatore di chiamata 5unzione viene de5inito per c#assi che a00iano una so#a 5unzione mem0ro: in ,uesto caso si usa anche #a denominazione di 5unzione o..etto' 7n a#tri casi #/operatore viene de5inito con ri5erimento a una 5unzione mem0ro predominante di una c#asse' 7# prototipo de##a 5unzione operatorBC assume #a 5orma: *+ operator()(li ta dei parametri); mentre #/istruzione di chiamata di ,uesta 5unzione ha #a 5orma: c(li ta argomenti); Ne# caso in esame #/o..etto c assume #/apparenza de# nome di una 5unzione9 i# numero di ar.omenti de##a 5unzione puo/ assumere ,ua#siasi ed e/ de5inito da# pro.ettista de##a c#asse' ./Giuseppe_N3mes1s
<63>
-peratore 8 L/operatore 3 viene ta#ora de5inito per .estire #e condizioni di errore che si producono a se.uito de##/app#icazione di una 5unzione mem0ro 5BC- per esempio #a 5unzione di in.resso/ uscita' / i# caso d osservare che ne# C++ non e de5inito #/operatore di va#utazione i5BcC- con c di tipo non standard- e in5atti esse rientra tra #e operazioni prede5inite per .#i o..etti de##e c#asse e non e/ ride5ini0i#e tramite operatore' 7# pro.ettista de##a c#asse puo/ pero/ rendere disponi0i#e a##/utente anche #a notazione i5BcC- attri0uendo opportunamente a essa una semantica comp#ementare a ,ue##a de##a notazione i5B3cC' Percio/ si dovra/ de5inire un operatore di conversione: operator ?oid*(); La 5unzione esamina .#i indicatori di stato e restituisce ) se vi sono errori- a#trimenti restituisce i# puntatore a c ne# caso di non errore' -peratori di s"ift 99 e :: G#i operatori di shi5t ven.ono ride5initi per consentire a##/utente di ese.uire su.#i o..etti di una c#asse C #e operazioni standard di in.resso uscita tipiche de##e varia0i# prede5nite' 7n partico#are ven.ono rese disponi0i#i a##/utente #e operazioni: cin!!c; //legge e memori11a le componenti di c cout<<c; //?i uali11a le componenti di c Sen.ono a##o scopo de5inite due 5unzioni operatore ne##a 5orma di 5unzioni ordinaria con due ar.omenti- i# primo di tipo istream Boppure ostreamC- i# secondo di tipo C- con i se.uenti prototipi: i treamD operator !! (i treamD inA 7D c); //legge le componenti di c o treamD operator << (o treamD outAcon t 7D c); //?i uali11a c 7n partico#are #e 5unzioni in esame possono essere dichiarate amiche de##a c#asse C' -peratore .: L/operatore in esame e/ detto se#ettore di mem0ro e consente- ne##a sua de5inizione standard- di puntare a una componente di un o..etto' 7ndicata con C una c#asse contenente una varia0i#e meme0ro pu00#ica e#- e con c un o..etto di C- si puo/ accedere a##a componente e# di c con #e notazioni: ...c.el... //accede alla componente el di c 7* p=Dc; //p punta a c ./Giuseppe_N3mes1s
Guida C++: Aspetti Avanzati p-!el // accede alla componente el di c a me11o di puntatore ordinario
<64>
L/accesso a##a componente e# di c puo/ anche essere ottenuto a mezzo di un ade.uata ride5inizione de##/operatore !L ' 7n ,uesto caso si ottiene una ma..iore 5#essi0i#ita/ perche/ #a 5unzione imp#icitamente richiamata- puo/ ese.uire una ,ua#siasi a#tra operazione che i# pro.ettista riten.a conveniente de5inire Bda ,ui i# termine smart point uti#izzato per i puntatori in esameC' La ride5inizione de##/operatore !L richiede #/introduzione di una c#asse ausi#iaria PC #a ,ua#e assume i# ruo#o di c#asse puntatore a##a c#asse C' La c#asse PC ese.ue #a redi5inizione de##/operatore !L - ne##a 5orma di 5unzione mem0ro- ed e/ dotata di una varia0i#e mem0ro che punta a C' Guesto schema aiuta a capire #/esposto: 6peci5ica de##a c#asse C cla 7{//contiene elemento el pu2lic: // truttura dati pu22lica * el; ... };//fine della pecifica di 7 6peci5ica de##a c#asse PC cla @7{//cla e au iliariaA redifini ce la fun1ione -! pri?ate: 7* pc; //?aria2ile mem2ro di tipo 7* pu2lic: //redifini1ione operatore -! 7* operator-!(){... return pc;} @7(7* p):pc(p){} //co truttoreA a egna a pc il punatatore a 7 }; // fine della pecifica di @7 Uso de##a c#asse C ?oid main(){ 7 c(...);//defini ce e ini1iali11a oggetto c @7 p(Dc); //richiama co truttore di @7;pApc puntano a 7 ...p-!el... //richiama p.operator-!() ... } La notazione p!Le# consente di accedere a##a componente e# di c' Piu/ in .enera#e i# compi#atore ese.ue una chiamata ricorsiva a##/oparatore unario post5isso !L 5ino a che non si accede a una c#asse che ha #a varia0i#e mem0ro di nome e#'
./Giuseppe_N3mes1s
<65>
L/operatore di indirizzamento NO puo/ essere app#icato ripetutamente a un o..etto- purche/ esso sia opportunamente ride5inito' Ad esempio: oJ i KJ G K prima viene chiamata #a 5unzione: o.operatorJK(i) 6e per ipotesi essa 5ornisce un o..etto c- a ta#e ar.omento viene ,uindi app#icata #a 5unzione: c.operatorJK(G) A00iamo percio/ o.operatorJK(i).operatorJK(G) Consideriamo per esempio una c#asse "atrice con e#emti di tipo E- potremo de5inire a##/interno di essa una prima 5unzione operatorNO con i# se.uente prototipo: ** operatorJK(int i); //re titui ce puntatore p alla riga i della matrice. La 5unzione in esame e/ richiamata ne##a 5orma mN i ON $ O e restituisce un puntatore p a##a ri.a i!esima di m' Una seconda 5unzione operatorNO puo/ avere i# prototipo: ** operatorJK(int G); //re titui ce puntatore a elemento adi riga i e colonna G La 5unzione in esame e/ richiamata ne##a 5orma p'operatorNOB$C e restituisce #/e#emento de##a matrice appartenete a##a ri.a puntata da p e a##a co#onna $' -peratori ne! e delete La redi5inizione de.#i operatori ne2 e de#ete per una speci5ica C#asse C puo/ essere #e.ata a##a possi0i#ita/ di app#icate a#.oritmi di .estione piu/ e55icienti di ,ue##i previsti da.#i operatori standard- in re#azione a##e speci5iche esi.enze di a##ocazione e dea##ocazione per .#i o..etti de##a c#asse C' 7n partico#are- #/utente potra/ richiamare .#i operatori ride5initi- uti#izzando #e usua#i notazioni: 7*p=neB 7; //alloca un oggetto della cla e 7 7*p=neB 7JnK //alloca un arra6 di oggetti della cla delete (p); //delalloca oggetto puntato da p e 7
./Giuseppe_N3mes1s
Guida C++: Aspetti Avanzati deleteJK(p); //dealloca arra6 di oggetti puntati da p A.#i operatori cosi/ ride5initi si app#icano #e medesime re.o#e viste per .#i operatori standard corrispondenti per ,uanto attiene a##a chiamata imp#icita di costruttori e distruttori e a##a inizia#izzazione de.#i o..etti' Le chiamate in esame ven.ono tradotte da# compi#atore ne##e se.uenti 5orme: neB 7 neB 7JnK delete (p) deleteJK(p) e9 e9 e9 e9 tra tra tra tra formato formato formato formato in in in in operator neB( i1eof 7) operator neB(n* i1eof 7) operator delete(p) operatorJK delete (p)
<66>
Conse.uentemente i# pro.ettista de##a c#asse C dovra/ uti#izzare i se.uenti prototipi di 5unzione: ?oid* operator neB( i1e&t n); //alloca un oggeto di n 26te ?oid* operator neBJK( i1e&t m); //alloca un oggetto di m 26te ?oid operator delete(?oid* p); //dealloca oggetto ?oid operator deleteJK(?oid*p); //dealloca arra6 di oggetti 7# tipo size_t e/ un tipo prede5inito- atto ad assumere per va#ore #a dimensione in 0Tte di un o..etto o di un insieme di o..etti' -peratore di conversione 7n una .enerica c#asse C possono essere de5inite una o piu/ 5unzioni per #a convenzione di un o..etto c di tipo C in un va#ore di tipo V prede5inito o de5inito da##/utente' La 5unzione di conversione assume necessariamente #a 5orma di 5unzione mem0ro de##a c#asse C e ha i# se.uente prototipo: operator W(); //con?erte un ?alore di tipo 7 in un ?alore di tipo W La 5unzione di conversione viene richiamata esp#icitamente con #e notazioni: c.operator W() oppure (W)c oppure Piu/ spesso essa e/ richiamata imp#icitamente' tatic&ca t <W! (c)
<67>
7no#tre #a #i0reria introduce i# concetto di stream B5#ussoC che rappresenta un/ astrazione dei dispositivi di in.resso/uscita- ha #o scopo di rendere #a scrittura dei pro.rammi indipendente da# partico#are dispositivo impie.ato- e semp#i5icare i# pro0#ema di porta0i#ita/ dei pro.rammi stessi' Lo stream consente di de5inire un/inter5accia semp#ice e uni5orma verso #/utente' a gerarc"ia di classi I)
7# meccanismo di ereditarieta/- 5a si che tutto cio/ che e/ possi0i#i rea#izzare con #e c#assi IpadriI e/ anche possi0i#i rea#izzare su##e c#assi derivate9 L/header 5i#e iostream contiene #e c#assi ios-istream-ostream-iostream: L/headre 5i#e 5stream inc#ude iostream- e contiene ino#tre #e c#assi i5streamo5stream- 5stream'
7no#tre ci sono a#tre c#assi- ,ua#i #a c#asse 6E; A"8U<- che .estisce i 0u55er di 7/> ed ese.ue #e operazioni di accesso a##e unita/ 5isiche de# sistema' U#teriori c#assi sono #e c#assi 76E;6E; A"- >6E;6E; A" e 6E;6E; A" per #e operazioni di #etture scrittura su strin.he- invece che su 5i#e' e classi istream e ostream Le c#assi 5ondamenta#i per #e operazione di 7/> primarie sono:
6i tratta di due c#assi predisposte per #e operazioni di 7/> se,uenzia#i su 5i#e di tipo testopartico#armente adatte per #/7/> primario Btastiera-video-stampanteC' 7n un pro.ramma percio/ ven.ono introdotte speci5iche varia0i#i su cui operare: i tream a; o tream 2; introducono varia0i#i a di tipo istream e 0 di tipo ostream' Le varia0i#i di tipo ostream e istream sono varia0i#i strutturate che contenono tutte #e in5ormazioni occorrenti per #a .estione de##o stream:
sui 0u55er associati a##o stream9 su##e dimensioni de##o stream9 su.#i errori9 su##a posizione corrente dei puntatori a##o stream9 su# I5ine 5i#eI
,li stream standard cin e cout Le operazioni di 7/> primarie avven.ono in partico#are a mezzo di due varia0i#i standard: ./Giuseppe_N3mes1s
<68>
C7N- di tipo istream- che rappresenta #a tastiera9 C>UE- di tipo ostream- che rappresenta i# video9
ta#i varia0i#i- a##/atto di esecuzioni di ciascun pro.ramma- risu#tano prede5inite e i 5i#e corrispondenti risu#tano aperti' A#cuni esempi: Lettura di un carattere CH Bcompreso #o spazioC cin.get(ch); int i=cinAget(); Lettura di una strin.a char J1%%K; cin.get( A1%%);//il carattere 9$n9 re ta nello con umato treamA non e9
char J1%%K; cin.getline( A1%%);//il carattere 9$n9 ?iene prele?ato ed eliminatoA en1a immetterlo in A#tre 5unzioni di ostream o treamD put(char c); o tremD Brite(char * A int n); esempio: char ch=9a9; cout.put(ch); char J1%%%K; cout.Brite( ); -perazioni di ingresso e uscita con formato *unzioni per il controllo del formato 7# contro##o de# 5ormato avviene a mezzo di opportune 5unzioni mem0ro de##a c#asse ios:
int 2idthBintC : de5inisce #/ampiezza de# campo9 int 2idthBC : de5inisce #/ampiezza de# campo9 int precisionBintC : de5inisce #a precisione per i numeri rea#i9 int precisionBC : restituisce #a precisione precedentemente de5inita9 ./Giuseppe_N3mes1s
Guida C++: Aspetti Avanzati esempio: cout.Bidth(C); cout<<9a9; cout<<F.1C1EQMPE; // tampa F.1C1EQA ei cifre ignificati?e cout.preci ion(C); cout<<F.1C1EQMPE;// tampa F.1CEA 0uattro cifre ignificati?e Manipolatori senza argomento #so dei manipolatori senza argomento
<69>
Ne##a #i0reria iostream sono de5initi numerosi meccanismi per ese.uire operazioni su##o stream- detti manipo#atori' A#cuni manipo#atori sono privi di ar.omento:
5#ush : svuota i# 0u55er di uscita end# : invia a cout i# carattere /_n/ ends : invia a cout i# carattere /_)_/ dec : de5inisce 0ase decima#e per .#i interi heF : de5inisce 0ase esadecima#e per .#i interi oct : de5inisce 0ase otta#e per .#i interi 2s : produce e#iminazione spazi senza input
6ono uti#izzati ne##a 5orma .enera#e: cout<<manipolatore; esempio: cout<<Q<<flu h; //produce lo ?uotamento del 2uffer a ociato al ?ideo cout<<he8<<8; //produce tampa a ?ideo del ?alore intero 8 in 2a e 1P Manipolatori con un argomento #so dei manipolatori con un argomento U#teriori manipo#atori con un ar.omento sono de5initi ne# 5i#e iomanip : ./Giuseppe_N3mes1s
Guida C++: Aspetti Avanzati set0aseBintC : posizione 0ase per interi setprecisionBintC : 5issa precisione per rea#i set2BintC : 5issa ampiezza de# campo setios5#a.B#on.C : posiziona a 1 i 5#a. di 5ormato resetios5#a.BintC : posiziona a ) i 5#a. di 5ormato
<70>
7 manipo#atori e#encati sono uti#izzati ne##a 5orma .enera#e: cout<<manipolatore(arg); esempio: cout. etpreci ion(1%);//produce la defini1ione di una preci ione pari a 1% ed e9 e0ui?alente a cout.preci ion(1%) ,estione dello stato dello stream Lo stato de##o stream e/ rappresentato da un insieme di indicatori de##o stado de##o stream a va#ori )- 1 oppure 5a#so- vero' 7 0it in esame sono memorizzati in una varia0i#e mem0ro de##a c#asse ios di nome state e tipo intero- in posizione opportuna' 7n partico#are .#i indicatori re.istrano #a condizione veri5icatasi a se.uito de##/esecuzione de##/u#tima operazione in.resso/uscita sono de5initi cosi/:
eo50it : assume va#ore vero ne# caso di 5ine 5i#e9 5ai#0it : assume va#ore vero ne# caso di un errore di 5ormato che non ha prodotto #a perdita di caratteriBerrore recupera0i#eC9 0ad0it : assume va#ore vero ne# caso di un errore che ha comportato #a perdita di dati Berrore irrecupera0i#eC9 .ood0it : assume va#ore vero ne# caso in cui non vi sia un errore Beo50it-5ai#0it-0ad0it sono posizionati a )C
7no#tre e/ de5inita #a 5unzione mem0ro: ?oid clear(int i=%); Uti#izzata per posizionare a .ood #o stato de##o stream- a##o scopo di procedere a##/operazione di 7/> dopo un errore' d ancora #o stato de##o stream puo/ essere esaminato a mezzo di una 5unzione mem0ro ./Giuseppe_N3mes1s
Guida C++: Aspetti Avanzati int rd tate()con t; La ,ua#e restituisce un va#ore intero che codi5ica i va#ori di eo50it- 5ai#0it- 0ad0it' esempio: //*e ta il ?alore di good2it 2ool.good()con t; cin.good(); //*e ta il ?alore di eof2it 2ool eof() con t; cin.eof(); //*e ta il ?alore di fail2it 2ool.fail()con t; cin.fail(); //*e ta il ?alore di 2ad2it 2ool.2ad() con t; cin.2ad(); //inoltre ?oid clear (int i=%); int rd tate() con t; -perazioni di I)- verso le memorie di massa Le operazione di 7/> per 5i#e ,ua#siasi costituiscono una .enera#izzazione di ,ue##e primarie9 occorre a..iun.ere:
<71>
#/ aperture de# 5i#e o..etto de##/operazione e ,uindi #a sua caratterizzazione9 #o svi#uppo de##e operazioni per 5i#e 0inari9 #e operazioni re#ative ai 5i#e di accesso diretto9 i# trattamento di eventua#i errori'
i5stream : per #/input9 o5stream : per #/output9 5stream : per operazioni di a..iornamento'
Le c#assi i5stream e o5stream sono derivate di istream e ostream e a..iun.ono a##e operazioni da esse de5inite anche #e operazioni su 5i#e ad accesso diretto' Apertura di un file ;ichiede un co##e.amento tra #/unita/ 5isica in o..etto de##/operazione e #a varia0i#e di tipo ./Giuseppe_N3mes1s
Guida C++: Aspetti Avanzati stream de5inita ne# pro.ramma' (ue distinti 5orma#ismi che coincidono pero/ ne##a semantica: ! Attraverso un costruttore: < tipofile ! nome'nterno(nome, ternoJA< ! Attraverso #a 5unzione open: < tipofile ! nome'nterno; nome'nterno.open(nome, ternoJA< C"iusura di un file
<72>
pecificatori !K);
pecificatori !K);
/ comp#ementare a ,ue##a di apertura e pone tramite a# co##e.amento tra #a varia0i#e di tipo 5i#e de5inita ne# pro.ramma e i# 5i#e disponi0i#e su##e memorie di massa' ! Attraverso a# 5unzione c#ose: < tipofile ! nome'nterno; nome'nterno.clo e(); Specifica delle operazioni da compiere Era .#i speci5icatori de##/operazione di apertura e/ inc#uso i# parametro mode- attraverso i# ,ua#e si de5iniscono #e caratteristiche de# 5i#e: //in5ormazioni re#ative a##a struttura interna de# 5i#e ios::0inarT !L apertura in moda#ita/ 0inaria Btesto per de5au#tC9 //in5ormazioni re#ative a# tipo di operazioni su# 5i#e ios::in !L apertura in input9 ios::out !L apertura di output- con sovrascrittura9 ios::in \ ios::out !L apertura di input e output9 ios::app !L apertura di output con append9 ios::ate !L dopo open si sposta a 5ine 5i#e9 //in5ormazioni re#ative a##a creazione ios::norep#ace !L in scrittura apre un 5i#e nuovo9 ios::nocreate !L in scrittura non crea i# 5i#e se non esiste9 ios::trunc !L se i# 5i#e esiste cance##a i contenuti'
./Giuseppe_N3mes1s
<73>
per de5au#t #/apertura e/ in moda#ita/ testo9 in input- se i# 5i#e non esiste #/apertura da errore9 in output- se i# 5i#e non esiste viene creato- se esiste viene cance##ato e sovrascritto9 per i5stream e/ ios::in9 per o5stream e/ ios::out9 per 5stream non vi e/ de5au#t- i# modo va esp#icato'
Apertura per sola scrittua L/operazione di apertura per so#a scrittura e/ de#icata perche/ puo/ produrre #a cance##azione indesiderata di un 5i#e esistete- percio/ si puo/ operare come se.ue:
se i# 5i#e da aprire e/ un 5i#e nuovo si usa /ios::norep#ace/9 se i# 5i#e deve essere scritto so#o in append- si usa /ios::out \ ios::app/9 se i# 5i#e da aprire puo/ essere cance##ato si usa #a moda#ita/ /ios::out/9 se i# 5i#e da aprire e/ un 5i#e .ia/ esistente che deve essere a..iornato- si usa #a moda#ita/ /ios::in \ ios::out/'
esempi: //aprire un file e terno1 con nome interno f1 if tream f1("e terno1"); //apre in output il file e terno1 con nome file interno fM of tream fM ("e ternoM"); //apre in aggiornamento il file e ternoF con nome fF f tream fF("e ternoF"A io ::inZio ::out); //apertura in input con open if tream f1; f1.open("e terno1"); //apertura in output di un file e i tenteA mod. append of tream fF; fF.open("file.out"Aio ::outZio ::app); //apertura in aggiornamento di un file e i tente f tream fC("file"Aio ::inZio ::out); // crittura di un 2locco di 26te in modalita9 2inaria of tream o ; o .open("e terno"Aio ::2inar6); float ?J1%%%K; int n= 1%%%* i1eof(float); // cri?e n 26te u o prele?andoli da ? o .Brite(reinterpret&ca t< un igned char*!(?)An); .... //lettura di un 2locco di 26te in modalita9 2inaria if tream i ; i .open("e terno"Aio ::2inar6); float ?J1%%%K; int n=1%%%* i1eof(float); ./Giuseppe_N3mes1s
Guida C++: Aspetti Avanzati //legge n 26te da i e li pone in ? i .read(reinterpret&ca t< un igned char*!(?)An); -perazione per file ad accesso diretto
<74>
#a .estione dei 5i#e con accesso diretto avviene a mezzo de##e 5unzioni di posizionamento e interro.azione su##a posizione' 6ui 5i#e ad accesso diretto tipicamete di opera in a..iornamento- a#ternando ,uindi operazione di #ettura con operazioni di scrittura' Per motivi di 0u55erizzazione tra #/operazione di scrittura e ,ue##a di #ettura deve essere interposta un/operazione di posizionamento'
istreamP see%.B#on. pC : Posizionamento per #ettura9 ostreamP see%pB#on. pC : Posizionamento per scrittura9 #on. te##.BC : <ornisce posizione per #ettura9 #on. te##pBC : <ornisce posizione per scrittura'
esempi: //(pera1ioni per file ad acce o diretto f tream f("e terno"Aio ::2inar6 Zio ::inZio ::out); //defini ce truttura del record truct +ecord{ ..... }; +ecord r; int n= i1eof(+ecord); long po =M%%%; ... long g=f.tellg(); ... long p=f.tellp(); f. eeRp(po *n); f.Brite(reinterpret&ca t<un igned char*!(Dr)An); <unzioni ausi#iarire Ba#cune .ia/ descritteC
ostreamP 5#ushBC : 6vuota #o stream9 int pee%BC : Copia i# carattere succ' dea##o stream senza estrar#o9 istreamP put0ac%Bchar cC : ;ipone i# carattere c ne##o stream9 istreamP i.nore Bint nK1-int de#imK ><C : 7.nora n caratteri9 void eat2hiteBC : strae spazi consecutivi9 int .countBC : <ornisce i# numero di caratteri #etti piu/ di recente'
./Giuseppe_N3mes1s
<75>
A$& ista Lista ordinata/non ordinata Po#itica di accesso a.#i e#ementi ;ea#izzazione ArraT Lista dinamica a puntatori %appresentazione con arra4 6truttura dati: ArraT statico piu/ eventua#mente una varia0i#e di tipo intero che mantiene i# numero corrente de.#i e#ementi ne##a #ista ed ino#tre varia0i#i che rappresentano indici su##/arraT' La se,uenza de.#i e#ementi e/ data da##a posizione stessa de.#i e#ementi de##/arraT' Lista non ordinata: 7nizia#izzazione Bne#emK)C 7nserimento in testa BpushC 7nserimento in coda ;icerca se,uenzia#e #iminazione in testa BpopC #iminazione di un e#emento dato Ana#isi de##/e#emento in testa BtopC Ca#co#o dei predicati emptT/5u## Bne#emKK)9ne#emKKNC Lista ordinata: Le operazioni devono .arantire #/ordinamento La .estione e/ onerosa perche/ richiede #o spostamento 5isico de.#i e#ementi in caso di inserimento e di e#iminazione %appresentazione con lista dinamica a puntatori 6truttura dati ;ichiede #a dichiarazione di un tipo ;ecord ./Giuseppe_N3mes1s
Guida C++: Aspetti Avanzati / costituita da un puntatore a# tipo ;ecord che rappresenta #a testa de##a #ista G#i e#ementi de##a #ista ven.ono a##ocati dinamicamente Lista non ordinata 7nizia#izzazione B7K)C 7nserimento in testa BpushC 7nserimento in coda ;icerca se,uenzia#e #iminazione in testa BpopC #iminazione di un e#emento dato Ana#isi de##/e#emento in testa BtopC Ca#co#o dei predicati emptT/5u## B7KK)/<AL6 C Lista ordinata
<76>
Le operazioni devono .arantire #/ordinamento La .estione e/ mo#to vanta..iosa in ,uanto non ce 0iso.no de##o spostamento 5isico de.#i e#ementi in caso di inserimento o e#iminazione 7n .enera#e un u#teriore vanta..io e/ dato da##a occupazione de##a memoria commisurata a##/e55ettiva necessita/ e a##a possi0i#ita/ di ri#asciare #e aree non piu/ uti#izzate in se.uito a##a cance##azione di un e#emento' A$& Pila Pi#a con po#itica di .estione L7<>: Last in <irst out 6tart Push Pop Eop mptT <u## La struttura dati prevede un indice!puntatore a##a testa de##a pi#a' )tart(t=%) @u h(pJtK=e;t==) @op(t--;e=pJtK) *op(e=pJt-1K) ,mpt6(t==%) "ull(t==5) A$& Coda
./Giuseppe_N3mes1s
Guida C++: Aspetti Avanzati Coda con po#itica di .estione <7<>: <irst in <irst out 6tart Append Pop mptT <u##
<77>
La struttura dati prevede una varia0i#e contenente i# numero de.#i e#ementi in coda e sia un indice!puntatore a##a testa che un indice!puntatore a##a coda' Una variante mo#to uti#izzata e/ #a coda circo#are' L/inserimento avviene in coda9 7# pre#ievo avviene in testa' )tart (neleme=%;t=c=-1) -ppend ((c==)X5;nelem==;0JcK=e;) @op (e=0JtK;(t==)X5;nelem--;) ,mpt6 (nelem==%) "ull (nelem==5) L/incremento de.#i indici puntatori e/ e55ettuato da# modu#o N %appresentazione degli A$& Pila e Coda con lista dinamica a puntatori / de# tutto simi#e a ,uanto .ia/ visto La struttura dati de##a Pi#a prevede un puntatore a##a testa' La struttura dati de##a Coda prevede un puntatore a##a testa ed uno a##a coda- cosi/ da 5aci#itare a#cune operazioni- ad esempio #/inserimento in codaBsenza scorrere tutta #a strutturaC A$& &abella Una ta0e##a e/ una struttura dati de5inita come un insieme 5inito di coppie: 7=(8A6) 8 appartiene WA 6 appartiene \ do?e 6=f(8)
F e/ detta chiave de##a ta0e##a9 7 tipi V e U possono essere tipi semp#ici o strutturati' ;appresentazione
./Giuseppe_N3mes1s
<78>
Le coppie possono essere ordinate per chiave oppure non ordinate per chiave %appresentazione statica con arra4 di record 7# record rappresenta #a coppia chiave!in5ormazione Un unico arraT monodimensiona#e i cui e#ementi sono i record %appresentazione con matrice Un unico arraT 0idimensiona#e La prima co#onna contiene #e chiavi La seconda co#onna i va#ori corrispondenti a##e chiavi Limitazione 5orte: #e chiavi e #e in5ormazioni devono essere de##o stesso tipo %appresentazione statica con due arra4 monodimensionali (ue arraT monodimensiona#i 7# primo contiene #e chiavi 7# secondo contiene i va#ori corrispondenti a##e chiavi %appresentazione mediante lista dinamica Ciascun e#emento de##a #ista e/ un record contenente tre campi: chiave- in5ormazionepuntatore a# prossimo'
./Giuseppe_N3mes1s
<79>
=Conclusioni
Con ,uesto u#timo capito#o termina #a mia Guida' 6pero che i concetti sopra esposti siano chiari- e perdonatemi ove ci 5ossero errori' Per ,ua#siasi in5o non esitatemi a contattarmi a# mio indirizzo !mai#' 6iete pre.ati di riportare #/autore de##a .uida se riportate parte dei essa' Grazie "i##e 6a#uti Cordia#i
#Name: Guida C++: Aspetti Avanzati #Author: Giuseppe_N3mes1s #Licence: GNU/GPL # !"ai#: dottor$e%i##_mister&tisca#i'it #(eve#opment: 3)/1*/*))+
./Giuseppe_N3mes1s