Sunteți pe pagina 1din 17

1.

a) Funcii inline n C++

Definirea unei funcii n interiorul unei clase este considerat inline. Functiile inline sunt eficiente in cazurile in care transmiterea parametrilor prin stiva este mai costisitoare (ca timp si executie) decat efectuarea operatiilor din corpul functiei. C++ ofer posibilitatea declarrii funciilor inline, care combin avantajele funciilor propriu-zise cu cele ale macrodefiniiilor. Astfel, la fiecare apelare, corpul funciei declarate inline este inserat n codul programului de ctre compilator. Fa de macrodefiniii (care presupun o substitutie de text ntr-o faz preliminar compilrii), pentru funciile inline compilatorul insereaz codul obiect al funciei la fiecare apel. Avantajul creterii de viteza se pltete prin creterea dimensiunii codului. Aadar, funciile inline trebuie s fie scurte. Exemplu: inline int comparare(int a,int b) { if (a>b) return 1; if (a<b) return 0; if (a==b) return -1; } Observaie : Este interzis folosirea n funciile inline a instruciunilor repetitive: for, while, do-while Deoarece compilatorul are nevoie de ntreaga definiie a unei funcii inline, funcia nu poate fi folosit dect n fiierul n care a fost definit.

2.

a) Operatorul de rezoluie n C++ - diverse utilizri

n C++ este definit operatorul de rezoluie (: : ) care permite accesul la un identificator global, dintr-un bloc n care acesta nu este vizibil datorit unei redeclarri. Se mai numete operator de acces. Principala aplicatie a operatorului este legata de clase si obiecte. Pentru definitiile functiilor membre aflate n afara declaratiei clasei, este necesara specificarea numelui clasei urmat de operatorul de rezolutie naintea numelui functiei. Clasa derivata poate specifica definitiile din clasa de baza utiliznd operatorul de rezolutie Exemplu: char sir[20]="Sir global"; void func() { char *sir; //variabila locala sir="Sir local"; puts(::sir); //afiseaza sirul global

puts(sir); //afiseaza sirul local }

3.

a) Suprancrcarea funciilor n C++

Limbajul C++ permite utilizarea mai multor funcii care au acelai nume, caracteristic numit suprancrcarea funciilor. Identificarea lor se face prin numrul de parametri i tipul lor. Suprancrcarea unei funcii nseamn utilizarea aceluiai identificator de funcie pentru cel puin dou funcii cu condiia ca s difere ntre ele prin tipuri i/sau numr de parametri (cu prototipuri diferite). n acest fel compilatorul poate selecta, la un moment dat, funcia care trebuie apelat. Exemplu: int suma (int a, int b) { return (a + b); } float suma (float a, float b) { return (a + b); } Dac se apeleaz suma (3,5), se va apela funcia corespunztoare tipului int, iar dac se apeleaz suma (2.3, 9), se va apela funcia care are parametrii de tipul float. La apelul funciei suma (2.3, 9), tipul valorii 9 va fi convertit automat de C+ + n float (nu e nevoie de typecasting)

4.

a) Parametri cu valori implicite n C++

C++ ofera posibilitatea declararii functiilor cu valori implicite ale parametrilor. La apelarea unei astfel de functii se poate omite specificarea parametrilor efectivi pentru acei parametri formali care au declarate valori implicite si se transfera automat valorile respective. Se pot specifica mai multe argumente cu valori implicite pentru o functie. Este obligatoriu ca numai ultimele argumente sa aiba astfel de valori si nu este permisa alternarea argumentelor cu si fara valori implicite. Exemplu: void fct(int, int=10); void tipareste(int i){ printf("%d ",i); } void fct(int p1, int p2){ tipareste(p1); tipareste(p2); } void main(void){ fct(1,2); fct(3); //implicit al doilea parametru actual este 10 } Rezultatul rularii acestui program va fi tiparirea

numerelor:

1 2 3 10s

5.

a) Variabile referin n C++; transferul parametrilor prin referine

C++ introduce un nou tip de date numit referin. Putem gndi c variabilele de acest tip sunt "pseudonime" ale unor variabile sau obiecte "reale". Aa cum un pseudonim nu poate exista fr corespondentul su real, nu pot fi definite referine singure. Caracterul & (ampersand) este utilizat pentru definirea referinelor. Exemplu: int ix; /* ix este variabla "reala" */ int &rx = ix; /* rx este "pseudonim" pentru ix */ ix = 1; /* de asemenea rx == 1 */ rx = 2; /* de asemenea ix == 2 */ Referinele pot fi utilizate ca argumente de funcii i valori de ntoarcere. Aceasta permite s se transmit argumentele prin referin sau s se ntoarc o modalitate de a accesa variabilele sau obiectele calculate. n C++ exista doua posibilitati de transmitere a parametrilor actuali catre o functie: - mecanismul de transmitere prin valoare - mecanismul de transmitere prin referinta Prin folosirea parametrilor formali referinta, se permite realizarea transferului prin referinta (transmiterea adresei) de o maniera similara celei din Pascal (parametrii VAR). Se elimina astfel necesitatea recurgerii la artificiul din C, adica utilizarea parametrilor formali pointeri, n cazul n care modificarile facute n interiorul functiei asupra parametrilor trebuie sa ramna si dupa revenirea din procedura. Transferul prin referinta este util si atunci cnd parametrul are dimensiune mare (struct, class) si crearea n stiva a unei copii a valorii ar reduce viteza de executie si ar ncarca stiva, mai performanta fiind transmiterea prin referinta; problema incarcarii stivei trebuie analizata mai ales in cazul programelor recursive..

1.

a) Operatorii new i delete din C++

Alocarea i eliberarea dinamic a memoriei se face n C cu anumite funcii de bibliotec (malloc(), free() i altele). Pe lng acestea, n C++ se introduc operatorii unari new (pentru alocare) i delete (pentru eliberare). Operatorul new poate fi utilizat n urmtoarele forme:
pt_la_tip = new tip; pt_la_tip = new tip(val_init); pt_la_tip = new tip[n];

unde: - tip = tipul variabilei dinamice, care poate fi un tip de date oarecare; - pt_la_tip = o variabil pointer de tip tip; - val_init = expresie cu a crei valoare se iniializeaz variabila dinamic. Varianta a treia se utilizeaz pentru alocarea memoriei pentru n elemente de tipul tip (un tablou cu n elemente) i n este o expresie ntreag. Se pot aloca i tablouri multidimensionale, specificnd toate dimensiunile. Iniializarea tablourilor nu este posibil. Operatorul new aloc spaiul necesar, corespunztor tipului, i ofer ca rezultat: - dac alocarea a reuit un pointer de tipul (tip *) coninnd adresa zonei de memorie alocate; - n caz contrar (memorie insuficient sau fragmentat), un pointer cu valoarea NULL (=0). Operatorul new poate fi folosit n urmatoarele situatii: Exemplu:
int * ip1, *ip2, *ip3; ip1=new int; // variabila ntreaga neinitializata ip2=new int(2); // variabila ntreaga initializata cu 2 ip3=new int[100]; // tablou de 100 de ntregi

Operatorul new poate fi folosit si la alocarea dinamica a obiectelor, n cazul acesta permitnd apelarea constructorului clasei. Operatorul delete este complementarul lui new si nlocuieste functia free() de dezalocare a memoriei dinamice alocate. Daca exista un destructor pentru obiectul care se dezaloca, acest destructor va fi apelat automat de catre delete . Operatorul delete are sintaxa delete pt_la_tip; unde pt_la_tip este adresa obinut n urma unei alocri cu operatorul new, utilizarea altei valori fiind ilegal, comportarea programului ntr-o astfel de situaie fiind nedefinit.

Ca i n cazul utilizrii funciilor de alocare i eliberare dinamic a memoriei, este necesar ca, dup ce unei variabile pointer i s-a atribuit o adres cu operatorul new, s nu i se atribuie alt adres i s nu se ias din blocul n care pointerul este declarat dect dup eliberarea vechii zone de memorie cu operatorul delete. n caz contrar, vechea zon de memorie va rmne ocupat, fra a mai putea fi utilizat, ceea ce poate duce, mai ales prin repetarea n cursul execuiei a operaiilor de mai sus la mari consumuri inutile de memorie. De reinut c grelile de mai sus nu sunt semnalate n cursul comiplrii sau al execuiei.

6.

a) Destructori

Destructorii sunt funcii speciale ale unei clase cu efect complementar constructorului. Ele sunt automat apelate pentru distrugerea obiectelor unei clase la sfritul programului. Destructorii au acelai nume cu cel al clasei de care aparin, precedati ns de caracterul ~. Fiecare clas are cel mult un destructor. Dac acesta lipsete, compilatorul genereaz automat unul cu efect nul. Funciile destructor nu primesc argumente. Se declar sub forma: class nume_clasa { public: nume_clasa( ) //constructor prestabilit . . . . . . . . . . . . . . . . //ali constructori ~ nume_clasa( ) //destructor . . . . . . . . . .. . . . . . //alte funcii membre }; Funcia destructor nu ntoarce nici un tip de date, nici chiar tipul void. Destructorii sunt utili mai ales pentru obiectele create prin alocarea dinamic a memoriei. Destructorii nu au argumente. Este chiar eronat s se defineasc argumente, deoarece destructorii sunt apelai implicit n momentul distrugerii: nu exist deci ansa s se specifice argumente efective.

7.

a) Funcii prietene n C++

Functiile prietene (friend) pot folosi membrii privati ai unei clase, desi ele nsele nu sunt membri. Functiile prietene au fost introduse pentru cazurile n care o functie coopereaza strns cu o clasa, dar nu face parte din acea clasa. O functie prietena este declarata asemanator cu o functie membra, avnd prototipul n interiorul clasei, precedat de cuvntul cheie friend. Exista si posibilitatea ca una sau mai multe functii membre ale unei clase sa fie functii prietene ale altei clase. Se poate declara si o clasa Y prietena a unei clase X, n acest caz toate functiile clasei Y sunt prietene ale clasei X si au acces nelimitat la membrii privati ai clasei X.

C + + permite accesul la datele membre private ale unei clase nu numai funciilor membre ale clasei respective, ci i altor funcii membre clasei numite funcii prietene. Ele pot fi independente sau membre altei clase. Declararea unei funcii prietene independente se face n interiorul clasei precednd prototipul funciei de cuvntul cheie friend astfel: class nume_clasa { public: friend tip_rez

nume_fct (<argumente>);

Indiferent de poziia prototipului, funciile prietene sunt publice . O astfel de funcie nu poate ntoarce o referin la clasa prieten. O funcie prieten poate accesa membri privai ai clasei direct prin operatorul .. O funcie prieten poate opera asupra unui obiect transferat ca argument. Ea folosete numele obiectului i un operator de rezoluie pentru a referi date sau funcii membre ale clasei. Dac un program conine o funcie membr a unei clase care este prieten altei clase se impun: - declararea corespunztoare a funciilor prietene - o anumit ordine n definiia claselor. Declararea funciilor prietene ce aparin unei clase se face sub forma: class nume_cls2 { public: . . . . . . . . . friend nume_cls1 :: nume_fct (<argumente>); } unde nume_cls1= numele clasei n care este funcia nume_cls2 = numele clasei cu care funcia este prieten. Folosirea funciilor prietene: - reprezint o metod de control a accesului la membrii unei clase - ofer o metod simpla de acces limitat din anumite funcii la datele unei clase - funcia care n lista de argumente are cel puin dou argumente din aceeai clas i care acceseaz argumente privai nu poate fi dect prieten.

8.

a) Clase prietene n C++

Clasa B este prieten clasei A dac toate funcsiile membre clasei B pot accesa direct membri privai ai clasei A. Pentru a defini clasa B prieten clasei A se introduce ntre membri publici ai clasei A o instruciune care s conin cuvntul friend urmat de numele clasei B sub forma: class B;

class A { public: . . . . . . . . . . friend class B; . . . . . . . . . . }; class B {. . . . . . . . }; Relatia friend nu este nici reflexiv, nici tranzitiv. De regul clasele prietene n C + + sunt independente, n sensul ca nici o clas nu mostenete membrii celeilalte clase.

2.

a) Clase, obiecte; date membre, funcii membre; implementare n C++; cuvntul cheie this

O clas este o reprezentare efectiv a unui tip abstract de date. Ea conine detalii de implementare pentru structurile de date i operaiile utilizate. Lucrm cu tipul abstract de date Intreg i proiectm propria noastr clas pentru el: class Intreg { attributes: int i methods: setValue(int n) Intreg addValue(Intreg j) } Definiie (Clas). O clas este implementarea unui tip abstract de date (TAD). Ea definete atributele i metodele care implementeaz structurile de date i operaiile din TAD, respectiv. Instanierile claselor se numesc obiecte. n consecin, clasele definesc proprietile i comportarea unei mulimi de obiecte. Conceperea de TAD-uri i declararea, ntr-un limbaj de programare, a claselor ce le sunt asociate formeaz obiectul proiectrii, iar conceperea algoritmilor pentru realizarea operaiilor i implementarea acestora prin definirea metodelor n limbajul de programare formeaz obiectul programrii orientate pe obiecte.

O trstur caracteristic a orientrii pe obiecte este ponderea mare pe care o are faza de proiectare n realizarea unei aplicaii.

Obiectele sunt identificabile n mod unic printr-un nume. Prin urmare, putem avea dou obiecte distincte cu acelai set de valori. Acest fapt este ntlnit n limbajele de programare "tradiionale" unde putem avea, de exemplu, doi ntregi i i j cu aceeai valoare "2". Observm utilizarea lui "i" i "j" n ultima propoziie ca nume pentru doi ntregi. Vom numi totalitatea valorilor la un moment dat ale atributelor ataate unui obiect starea obiectului. Definiie (Obiect). Un obiect este o instaniere a unei clase. El poate fi identificat n mod unic prin numele su i n fiecare moment are o stare care reprezint valorile atributelor sale n acel moment. Starea unui obiect se schimb n funcie de metodele care sunt aplicate asupra sa. Numim aceast posibil secven de schimbari ale strii comportarea obiectului. Definirea functiilor membre se poate face fie ca functii inline, la declararea lor n cadrul clasei, fie n exteriorul clasei. Pentru definitiile functiilor membre aflate n afara declaratiei clasei, este necesara specificarea numelui clasei urmat de operatorul de rezolutie naintea numelui functiei. Functiile membre pot avea acces la orice membru al clasei respective. Accesul la membrii de date ai instantei curente se face direct, prin numele lor. Pentru apelul functiilor membre publice sau pentru accesul la datele publice ale unui obiect, din functii care nu sunt membre, se folosesc operatorii de selectie (.) si (->), ca n cazul structurilor si uniunilor din C. Functiile membre statice efectueaza operatii care nu sunt asociate obiectelor individuale, ci ntregii clase. Din acest motiv, la apelarea lor nu este obligatorie indicarea unui obiect. Pentru a defini functiile membre sunt necesare referiri la datele membre ale clasei fara a specifica un obiect anume. La apelare, functia este informata asupra identitatii obiectului asupra caruia va actiona prin transferul unui parametru implicit care reprezinta adresa obiectului. De exemplu, n cazul apelului: s1.Push(3), functia Push() priseste si adresa stivei s1 n afara de valoarea 3. Exista situatii n care este necesar ca adresa obiectului sa fie utilizata n definitia functiei. Ne putem referi la acest pointer prin cuvntul cheie this, declarat implicit n orice functie si initializat sa indice nspre obiectul pentru care este invocata functia membra. Principala utilizare a lui this este la scrierea functiilor care manipuleza direct pointeri.

3.

a) Efectul modificatorilor de acces public, protected, private n C++

n C++ se disting dou tipuri de motenire: public i privat. Implicit clasele deriv n mod privat una din cealalt. n consecin, trebuie s se informeze explicit

compilatorul pentru a utiliza motenirea public. Tipul de motenire influeneaz drepturile de acces la membrii unor supraclase. Orice este declarat private ntr-o supraclas va fi inaccesibil n subclas. Utiliznd motenirea public, orice este public rmne public. Atunci cnd se utilizeaz motenirea privat, orice nu este privat n supraclas devine privat n subclas. Efectul cumulat al dreptului de acces din supraclas i al modului de motenire asupra dreptului de acces din subclas ai membrilor supraclasei este complet artat n tabelul Tip de motenire private protected public private inaccesibil private private protected inaccesibil protected protected public inaccesibil protected public

Coloana din stnga listeaz drepturi posibile de acces pentru membrii supraclaselor. Un rol special are un al treilea mod de acces: protected. Acesta este utilizat pentru membri care s fie direct utilizabili n subclase dar care s nu fie accesibili din afar. Astfel, s-ar putea spune c membrii de acest tip sunt ntre private i public prin aceea ca ei pot fi utilizai n ierarhia de clase avnd drept rdcin clasa corespunztoare, utilizndu-se i tipul de motenire protected. Urmtoarele coloane arat drepturile de acces care rezult pentru membrii unei supraclase n funcie de tipul de motenire.

9.

a) Constructori; constructori de copiere; implementare n C++

Constructorul este o funcie membru special a unei clase, care are acelai nume cu clasa creia i aparine. El servete la crearea i iniializarea obiectelor i de aceea este apelat implicit de fiecare dat cnd se creaz noi instanieri ale clasei. Declarare i caracteristici ntr-o clas pot exista nici unul, unul sau mai multi constructori. Dac nu este nici un constructor, compilatorul genereaz automat unul care este public, fr argumente i cu o list vid de instruciuni. O funcie constructor nu ntoarce un tip de date, deci n corpul ei nu trebuie folosit return. Se declar un constructor prin : class nume_clasa { public: nume_clasa (); // constructor prestabilit fr argumente nume_clasa (nume_clasa & c); // constructor de copiere nume_clasa ( argumente); // constructorii cu argumente } ;

La declararea i la definirea unei funcii constructor tipul void nu poate fi specificat ca tip returnat.Constructorii pot avea argumente (inclusiv din cei implicii) i pot fi supradefinii. Pointeri catre constructori nu se pot folosi, deci adresa lor nu ne este accesibi. ntr-un constructor putem folosi operatorii new i delete. Un constructor prestabilit nu are argumente sau are o list de argumente n care toi argumente folosesc argumente prestabilite. Dac nu precizm valori pentru toate argumentele, funcia constructor, ca orice funcie, folosete valori implicite. Constructor de copiere Acest constructor se folosete n C + + pentru a declara un obiect de tip clas i pentru a transfera un obiect ca argument sau ca rezultat al unei funcii nsoite de o atribuire respectiv de iniializarea obiectului cu datele altui obiect de acelai tip. Dac un astfel de constructor de copiere nu este declarat ntr-o anumit clas, compilatorul genereaz automat unul care iniializeaz datele unui nou obiect cu valorile corespunztoare dintr-un obiect specificat prin copiere membru cu membru ca la atribuirea standard. Pentru a declara un constructor de copiere pentru clasa nume_clasa trebuie s specificm un argument unic de tip referin la un obiect de acelai tip nume_clasa sub forma: nume_clasa (const nume_clasa & nume_obiect); unde modificatorul const asigur c obiectul de intrare nu poate fi modificat. Constructorul de copiere acioneaz ca orice apel de funcie obinuit. Un constructor de copiere poate promova mai multe argumente, dar cele suplimentare trebuie s fie cu valoare implicit pentru a permite copierea automata a obiectelor la apelul funciei sau la ntoarcerea din funcie. Constructorul de copiere generat implicit de compilator copiaz doar datele membre n cazul unor structuri dinamice i de aceea se recomand declararea de utilizator a constructorului de copiere pentru clasele care se refer la acest tip de structuri de date.

10. a)

Motenire, tipuri de motenire efecte; implementare n C++

Motenirea este mecanismul care permite unei clase A s primeasc proprieti ale unei clase B. Spunem "A motenete de la B". Obiectele clasei A au astfel acces la atributele i metodele clasei B fr a fi nevoie ca ele s fie redefinite. Stabileste o relatie de genul "este un/este o" (is-a)

Clas de baza = clasa de la care se preia structura i comportamentul Clasa derivat = clasa care preia structura i comportamentul In principiu, fiecare dat sau funcie membru a clasei de baz se motenete n clasa derivat (difer doar protecia acestora). Exist i excepii: - Constructori ii destructorii - Suprancrcarea operatorului Acetia nu se motenesc, fiind metode specifice clasei

Tipuri de Motenire Motenire simpl clasa derivat preia caracteristicile i metodele unei singure clase de baz Motenire multipl clasa derivat preia caracteristicile i metodele de la mai multe clase de baz Obiectele unei subclase pot fi utilizate acolo unde pot fi utilizate i obiectele supraclasei corespunztoare. Aceasta se datorete faptului c obiectele subclasei au o comportare comun cu obiectele supraclasei. n literatur se ntlnesc i ali termeni pentru "supraclas" i "subclas". Supraclasele sunt numite i clase printe (n englez parent classes ). Subclasele se numesc i clase copil (n englez child classes ) sau clase derivate (n englez derived classes ). Bineneles, se poate moteni i de la o subclas fcndu-se din aceasta supraclas unei noi subclase. Aceasta conduce la o ierarhie a relaiei supraclas/subclas. Dac se deseneaz aceast ierarhie, se obine un graf al motenirii. Un mod obinuit de a desena astfel de scheme este utilizarea sgeilor pentru a indica motenirea ntre dou clase sau obiecte, sgeata pornind de la subclas la supraclas.

11. Motenire

multipl; rezolvarea conflictelor de nume; clase virtuale; implementare n C++

Faptul c o clas A motenete de la mai mult de o clas, adic A motenete de la clasele B1, B2,..., Bn, cu n>1 se numete motenire multipl. Acest fapt poate introduce conflicte de nume n A dac cel puin dou din supraclasele sale definesc propieti cu acelai nume. Aceste conflicte pot fi soluionate in cel puin dou moduri: - Supraclasele se dau ntr-o anumit ordine i aceasta definete care proprietate va fi accesibil. Celelalte vor fi "ascunse".

- Subclasa trebuie s rezolve conflictul definind explicit cum vor fi utilizate proprietile cu acelai nume din supraclasele sale. Prima soluie nu este prea convenabil deoarece ea introduce consecine implicite n legtur cu ordinea n care clasele motenesc una de la alta. Pentru cazul al doilea, subclasele trebuie s defineasc n mod explicit proprietile care sunt implicate ntr-un conflict de nume. Mostenirea multipla reprezinta abilitatea de a defini o clasa derivata simultan din mai multe clase (numite clase de baza). Prin motenire multipl se nelege faptul c o subclas are mai mult dect o singur supraclas. Aceasta permite subclasei s moteneasc proprietile a mai mult dect o supraclas i s "combine" proprietaile supraclaselor sale. Dei motenirea multipl este un mecanism puternic orientat pe obiecte, problemele introduse de conflictele de nume au determinat pe unii autori s l "condamne". Deoarece rezultatele motenirii multiple pot fi ntotdeauna obinute utiliznd motenirea (simpl), unele limbaje de programare orientate pe obiecte nu permit utilizarea sa. Totui, utilizat cu atenie, n anumite condiii, motenirea multipl reprezint un instrument elegant i eficient de proiectare orientat pe obiecte.

12. a)

Clase abstracte; implementare n C++

O metod sau o clas abstract se declar folosind cuvntul cheie abstract. De exemplu public abstract double calcPay( doublehours ); Dintr-o clas abstract nu se poate instania niciun obiect Fiecare subclas a unei clase abstracte care va fi folosit pentru a instania obiecte trebuie s ofere implementri pentru toate metodele abstracte din superclas. Clasele abstracte economisesc timp deoarece nu trebuie s scriem cod inutil care n-ar fi executat niciodat. O clasa abstract poate mosteni metode abstracte dintr -o interfat sau dintr-o clas. Clasele abstracte se definesc exact la fel ca i clasele obinuite. Totui, unele din metodele lor sunt specificate ca fiind n mod necesar definite de subclase. Se specific prototipul lor care conine tipul pe care l ntorc, numele i argumentele, dar nu i definiia. Se poate spune c se omite corpul metodei, sau, altfel spus, se specific "nimic". Aceasta se exprim adugnd "=0" dup prototipul metodei: class ObiectDesenabil { ... public: ... virtual void print() = 0;

}; Aceast definiie de clas va fora fiecare clas derivat de la care urmeaz s se creeze obiecte s defineasc o metod print(). Aceste declaraii de metode sunt numite i metode pure. Metodele pure trebuie de asemenea s fie declarate virtuale, deoarece se dorete s se utilizeze obiecte numai de la clasele derivate. Clasele care definesc metode pure se numesc clase abstracte

13. a)

Clase generice; modaliti de implementare n C++

Clasele colecii conin obiecte de un tip particular (de exemplu o list nlnuit de ntregi sau un tablou de structuri. Se pot defini familii de clase colecii, membrii acestora diferind numai prin tipul elementelor. Considerm clasa tablou de ntregi: pentru a folosi un tablou de reali, de compleci sau de iruri de caractere s-ar putea copia implementarea clasei, modificnd tipul datelor i numele clasei. Astfel am avea clasele intArray, StringArray, ComplexArray, etc. Familia de clase poate fi reprezentat printr-o clas generic (parametrizat). Aceasta specific modul n care pot fi construite clasele individuale, care se deosebesc numai prin tipul elementelor pe care le conin. Atunci cnd scriem definiia unei clase, trebuie s putem preciza dac aceast clas definete un tip generic. Totui, nu tim cu care tipuri va fi utilizat clasa. n consecin, trebuie s putem defini clasa cu ajutorul unui "lociitor" la care ne referim ca i cnd ar fi tipul asupra cruia opereaz clasa. Astfel, definiia clasei ne este dat ca un model sau ablon (traducerea termenului englez template) al unei clase efective. Definiia clasei este creat de fapt atunci cnd declarm un obiect particular. O versiune a ablonului pentru un argument particular poart numele de specializare. Utilizarea unei clase generice presupune generarea de ctre compilator a fiecrei clase individuale, corespunztor tipurilor care instaniaz clasa generic. O clas generic se reprezint astfel: template <list_argumente_generice> declarare_clas; Instanierea unei clase generice se face prin: nume_clas <list_argumente_concrete> nume_obiect; Definim clasa generic (parametrizat): template <class T> class Array{ public: Array(int d=10): a(new T[dim]), dim(d){} ~Array(){delete a;} private: T *a;

int d; }; Funciile generice pot fi suprancrcate, cu condiia ca instanele s aib semnturi diferite. De exemplu: template <class T> class Array{. . .}; //clasa generica template <class T> T suma(Array<T>, int); //functie generica template <class T> T suma(T*, int); //functie generica supraincarcata void main(){ Array<int> A[100]; //instantiere clasa generica int a[100]; int s1 = suma(A, 100);//instantiere functie generica int s2 = suma(a, 100); }

14. a)

Suprancrcarea operatorilor binari n C++

Un operator binar pentru o clas poate fi implementat ca funcie membr cu un argument sau ca funcie nemembr cu dou argumente dintre care unul este un obiect al clasei sau o referin la un obiect al clasei. Vom implementa operatorul += pentru concatenarea a dou obiecte de tip String. Cnd optm pentru varianta implementrii acestui operator ca funcie membr cu un singur argument, presupunnd c y i z sunt obiecte ale clasei String, y+=z este tratat ca i cum am fi scris y.operator+=(z). Este invocat funcia membr operator+= declarat astfel: class String { public: const String& operator+=(const String&); ... }; Dac += este implementat ca operator binar, operaia y+= z este tratat ca i cum n program am fi avut instruciunea operator+=(y,z), invocndu-se funcia friend nemembr operator+= declarat astfel: class String { friend const String& operator+=(String&, const String&); ... };

15. a)

Suprancrcarea operatorilor unari n C++

Un operator unar pentru o clas poate fi implementat ca funcie membr fr argument sau ca funcie nemembr cu un argument. Acest argument trebuie s fie un obiect al clasei sau o referin la un obiect al clasei.

Vom defini n acest capitol clasa String i vom implementa pentru aceasta operatorul unar s! prin care vom testa dac un obiect este vid sau nu. Presupunnd c s este un obiect al clasei String, la ntlnirea expresiei !s compilatorul va genera apelul s.operator!(). Operandul s este obiectul clasei pentru care a fost invocat apelul funciei membre operator!a clasei String. Funcia este declarat n definiia clasei astfel:

class String { public: bool operator!() const; ... }; Acest operator unar poate fi implementat i ca funcie nemembr cu un argument, n dou feluri: fie cu un argument care este obiect al clasei, fie cu argument ca referin la obiect. Pentru un obiect s din clasa String, apelul !s este tratat prin apelul operator!(s) care invoc funcia nemembr friend a clasei String declarat astfel:

class String { friend bool operator!(const String&); ... }; Ca regul practic n alegerea uneia dintre cele dou variante, trebuie evitat folosirea funciilor nemembre friend dac folosirea lor nu este absolut necesar.

16. a)

Legare dinamic: funcii membre virtuale; implementare n C++

n limbajele de programare cu reguli stricte de stabilire i de utilizare a tipurilor, tipurile trebuie declarate naintea utilizrii lor. Aceasta implic definirea variabilei, care produce rezervarea spaiului de ctre compilator. Pentru a se putea urmari tipul obiectului adresat de pointer la un moment oarecare, este necesara identificarea versiunii functiei care trebuie apelata n timpul executiei programului. Acest mod de lucru se numeste legare dinamica (late binding).s Definiie (Legare dinamic). Dac tipul T al unei variabile cu numele N este implicit asociat prin coninutul su, spunem c N este legat dinamic de T. Procesul de asociere se numete legare dinamic. Cele dou legari difer prin momentul cnd tipul este legat de variabil.

Functiile membre pentru care se realizeaza legatura dinamica se numesc functii virtuale si se declara cu ajutorul cuvntului cheie virtual. De exemplu, declaratia functiei AfiseazaDate, se va modifica astfel n cadrul clasei Persoana: virtual void AfiseazaDate();

17. a)

Suprancrcarea operatorului de conversie a tipurilor n C++

n C++ la evaluarea unei expresii se efectueaz conversii implicite pentru tipurile predefinite. Deoarece nu exist conversii implicite de la o clas la un tip predefinit, programatorul i poate defini conversii explicite prin suprancrcarea unui operator de conversie al clasei. Astfel pentru clasa C, funcia membru nestatic de conversie C::operator T() unde T este un nume de tip primitiv realizeaz conversia de la tipul C la tipul T. Aceasta nu specific nici un tip de rezultat ntors, deoarece se returneaz implicit valoarea obiectului convertit la tipul pentru care este definit conversia i nu are parametri. Funcia operator primete ca prim parametru implicit adresa obiectului i ntoarce valoarea convertit de tipul numelui funciei operator de conversie. Apelul explicit al funciei de conversie de la un obiect din clasa C la tipul primitiv T se specific prin T(obiect) sau (T) obiect. Pentru conversia unui obiect ntre dou clase C1 i C2,C1->C2 se definete funcia membru operator de conversie C1::operator C2(); Pentru ca aceast funcie s aib acces la membrii clasei C2, se declar funcie prieten clasei C2. Sunt premise astfel conversii ntre o clas i un tip predefinit sau ntre dou clase, dar nu de la un tip predefinit la o clas. Constructorii cu un singur argument pot fi folosii ca funcii de conversie de la tipul argumentului la clasa constructorului. Acest efect nu este ntotdeauna dorit, i pentru a-l evita, constructorul se declar precedat de cuvntul cheie explicit. Dac o metod a unei clase folosete parametri care sufer conversii implicite, metoda se va defini ca funcie prieten, nu ca funcie membr. Definim ca exemplu clasa Inch:
class Inch{ double inch; double cm; public: explicit Inch(double i=0.) : inch(i){}; //ctor void Inch_cm(){ cm=2.54*inch;}; operator int() const {return int(inch+0.5);}; //fctie conversie

S-ar putea să vă placă și