You are on page 1of 48

PROGRAMAREA ORIENTATĂ PE OBIECTE

ÎNDRUMAR DE LABORATOR

Liviu Şerbănescu UNIVERSITATEA HYPERION

LISTA LUCRĂRILOR

1. Iniţiere într-un mediu de programare. Structura unui program C++. 2. Noţiunea de clasă şi obiect. Operatori specifici C++. 3. Clase şi moşteniri. Clase de bază virtuale 4. Constructori şi destructori 5. Modificatorii şi specificatorii de acces 6. Date şi funcţii de tip friend şi statice 7. Polimorfism, funcţii virtuale 8. Supraîncărcarea operatorilor 9. Fluxuri de intrare/ieşire.Obiecte standard 10. Fluxuri de intrare/ieşire.Operatii de intrare/iesire cu fisiere 11. Tratarea excepţiilor 12. Utilizarea claselor wxWidgets (I) 13. Utilizarea claselor wxWidgets (II) 14. Teste.

LABORATORUL NR.1 INIŢIERE ÎNTR-UN MEDIU DE PROGRAMARE. STRUCTURA UNUI PROGRAM C++ Scop: 1. Familiarizarea cu mediul integrat CodeLite. 2. Înţelegerea structurii unui program scris în limbajul C++. 3. Înţelegerea bibliotecilor ce utilizează programarea orientată pe obiecte.

Consideraţii teoretice: Mediul integrat - OpenSource - CodeLite Un spaţiu de lucru (workspace) detine un numar de proiecte, de exemplu, acestea pot avea legătură unele cualtele sau nu Crearea unui spaţiu de lucru se realizează prin selectarea " "Workspace | Create new Workspace"" Un proiect (project) poate avea va rezultat în urma compilării şi apoi a link-editării un executabil, o bibliotecă dinamică (*.DLL), o bibliotecă statică(*.LIB), etc. Proiectul în sine conţine toate informaţiile necesare pentru a produce o aplicaţie de un anumit tip (aplicaţie consolă, aplicaţie grafică ce utilizează un anumit set de controale vizuale, aplicaţie cu obiecte grafice, etc). Fişierul ce conţine informaţii despre spaţiul de lucru se numeşte <workspace-name>.workspace Fişierul ce conţine informaţii despre proiect este <project-name>. prj Pentru crearea unui proiect nou se va utiliza opţiunea GUI (Graphics User Interface).

Structura unui program C++ Un programC++ cuprinde următoarele elemente pricipale:
✗ ✗ ✗ ✗ ✗

operatori (aritmetici, logici, etc) instrucţiuni (de decizie, de parcurgere a unei bucle, etc) funcţii (apelate din cadrul bibliotecilor sau definite de utilizator) variabile şi constante funcţia main()

Textul unui program poate fi scris într-un fişier sau în mai multe fişiere. Un program va avea o singură funcţie main() indiferent dacă este scris într-un singur fisier sau în mai multe fişiere. Programul compilat şi linkeditat va incepe întodeauna prin lansarea în execuţie a instrucţiunilor şi funcţiilor din cadrul lui main(). Prin ieşirea din funcţia main() se încheie şi execuţia programului.

Desfăşurarea lucrării: 1. Lansarea mediului CodeLite, şi studierea principalelor componente ale interfeţei acestuia 2. Crearea unor spaţii de lucru 3. Crearea unui proiect pentru aplicaţie consolă 4. Compilarea unui exemplu. Modificarea setărilor implicite de compilare. 5. Executarea separată aLink-editării pentru o aplicaţie. Modificarrea setărilor implicite pentru link-editare 6. Adăugarea bibliotecilor cu clase. 7. Recompilarea (având şi biblioteci cu clase) 8. Relinkeditarea .

Proiectarea de programe utilizand clase se numeste programare orientat pe obiecte (OOP.* ->* new delete FORMA ::a ::f() OB.accesează variabilele globale chiar dacă au acelaşi nume cu cele locale . O parte din metode vor fi utilizate de cel ce utilizează clasa în cadrul aplica țiilor.Object Oriented Programming). Date + Metode = Obiect sau Clasă (tipul datei) Principiul încapsulării (ascunderea informaţiei ce stă la baza realizării clasei): accesul la datele membre se poate face numai prin intermediul setului de metode asociat. un vector de 10 întregi: new int[10]. OPERATORI SPECIFICI C++ Scop: 1. În cadrul unei clase pot fi declarate inclusiv variabile de tip structură sau de tip clasă.întoarce valoarea (OB valoare) .*a OB->*a new tip delete a delete a[] Operaţia realizată . ex ptr. Înţelegerea noţiunilor de clasă şi obiect 2. iar altă parte va fi invizibilă pentru utlizatorul final (atât codul cât și apelul acestora).2 NOŢIUNEA DE CLASĂ ŞI OBIECT. Se execută exemplele corespunzătoare din secţiunea TESTE . întoarce NULL în caz de eşec altfel întoarce adresa alocată eliberează zona de memorie arată adresa obiectului curent (în care ne aflăm) iar *this este valoarea obiectului curent this this/ *this Desfăşurarea lucrării: 1. Un asemenea ansamblu poarta denumirea de obiect sau clasa (tipul datei). Conform principiului încapsulării utilizatorul nu are acces la date ci numai la metodele pe care dezvoltatorul clasei le-a lăsat pentru a putea fi apelate. Notiuni fundamentale: Datele (membrii) şi funcţiile (membrele / metodele) unei clase Datele sunt reprezentate prin declarațiile variabilelor din cadrul clasei. Operatorii specifici C++ OPERATORUL SIMBOLU L rezoluţie / indicator acces valoare valoare new delete this :: .LABORATORUL NR.accesează membrii/membrele claselor . Obiectul este caracterizat complet prin metodele asociate. Înţelegerea operatorilor specifici C++ Consideraţii teoretice: CONCEPTE FUNDAMENTALE Ideea de baza de la care pleaca programarea orientata obiect este de a grupa structurile de date cu operatiile care prelucreaza respectivele date.întoarce valoarea (OB pointer) alocă memorie.

în momentul declarării . iar fiecare clasă derivată poate servi ca bază pentru alte clase derivate. Dintr-o clasă (numită clasă de bază) pot fi derivate mai multe clase. Astfel se realizează o ierarhie de clase. modificate în cadrul clasei DER1 . Clasa de bază nu este afectată şi nu trebuie recompilată. destructor şi mecanismul de moştenire Clasa de bază. pot fi date din clasa BAZA. numită clasă de bază. Adică duncţia constructor din clasa de bază este executată înaintea celei din clasa derivată iar destructorul unei clase derivate este executat înaintea celui din clasa de bază. numită clasă derivată.LABORATORUL NR. sau ambele. clasa derivată. CLASE DE BAZĂ VIRTUALE Scop: 1.lista_argumente_2):nume_clas a_baza (lista_argumente_1v) { corpul constructorului } unde: lista_agumente_1 este lista de argumente a constructorului bazei (tipuri +variabile). modificator_acces nume_clasă_baza_n >] Funcţiile constructor. primele argumente din constructorul clasei derivate trebuie să coincidă cu argumentele constructorului ales din clasa de bază. fiecare nivel al ierarhiei acumulează caracteristicile (membri +membre) claselor "părinte" (bază) şi le adaugă un anumit grad de specializare. clasa DER12 moşteneşte de două ori clasa BAZA. pe care le completează cu propietăţi (membri+membre) noi. cele constructor sunt executate în ordinea derivării iar funcţiile destructor sunt executate în ordine inversă. pot avea funcţii constructor şi/sau destructor. Acest lucru determină o ambiguitate când clasa DER12 vrea să aibă acces la datele din clasa BAZA.prin numărul şi tipul argumentelor) De asemenea. nume_clasa_baza_n(lista_argumente_n1v) >] { corpul constructorului } unde lista_argumente_n1v sunt incluse în lista_argumente_1v Clase de bază virtuale Presupunem ca avem o clasă BAZA şi două clase ce derivă din BAZA. lista_agumente_1v este lista de argumente a constructorului bazei (variabile) iar lista_agumente_2 este lista de argumente a suplimentară. Utilizarea funcţiilor şi a claselor de bază virtuale Consideraţii teoretice: Procedeul de derivare permite definirea unei clase noi. o dată prin DER1 şi o dată prin DER2. Sintaxa declaraţia clasei derivate în cazul unei singure clase de bază: class nume_clasa_derivata : modificator_acces nume_clasă_baza iar în cazul mai multor clase de bază (moştenire multiplă): class nume_clasa_derivata : modificator_acces nume_clasă_baza_1 [<. (de ex. lista_argumente_2):nume_clasa_baza_1(lista_argumente_11v)[<. declaraţia (fişierul header) şi codul obiect (fişier obj / dll/ lib) ale clasei de bază sunt suficiente pentru crearea unei clase derivate. Sintaxa este: nume_clasă_derivată::nume_clasă_derivată(lista_argumente_1.3 CLASE ŞI MOŞTENIRI. Deci. În cazul în care o clasă moşteneşte proprietăţile mai multor clase avem moştenire multiplă. Când se explicitează costructorul din clasa derivată trebuie să se specifice care din constructorii clasei de bază este apelat ( constructorii diferă între ei . care moşteneşte propietăţile (membri + membre) unei clase deja definite. Apoi din DER1 şi DER2 derivăm o altă clasă denumită DER12 . Înţegerea moştenirii claselor 2. Când o clasă de bază şi una derivată conţin atât funcţii constructor cât şi destructor. specifică constructorului clasei derivate (tipuri +variabile) iar în cazul moştenirii multiple sintaxa este: nume_clasă_derivată::nume_clasă_derivată (lista_argumente_1. Pornind de la clase simple şi generale. numite DER1 şi DER2.

b2=0.} B(int a1_. Se utilizează cuvântul cheie virtual înaintea modificatorului de acces.d2=0. public: A() {a1=0. class DER2: virtual public BAZA {}.diamant class A{ int a1. #include <stdio.} }. Se rulează exemplele din secţiunea teoretică 2. std::cin>>m.b2.a2=0.//astapta o tasta return 0.a2. class D: public B.} }. Se continuă cu exemplele corespunzătoare din secţiunea TESTE . class C: virtual public A {int c1. b2=0. } // cuvantul cheie virtual permite eliminarea duplicatelor clasei A Desfăşurarea lucrării: 1. public: C():A() {c1=0. Pentru a rezolva această ambiguitate.c2. int m.int c2_): A() {c1=c1_.} C(int c1_. c2=c1_.} void afis1() {std::cout<<"/n c1="<<c1<<" c2="<<c2.sau modificate în cadrul clasei DER2 .} }.int a2_) {a1=a1_.h> #include <iostream> //mostenire de tip .atât DER1 cât şi DER2 au câte o copie a clasei BAZA). C++ include un mecanism prin care doar o copie a clasei BAZA va fi inclusă în clasa DER12.} }. (ex: class DER1: virtual public BAZA {}.} A(int a1_.afis(). x1. int main(int argc. public C { int d1. char **argv) { D x1.C() {d1=0.} void afis() {std::cout<<"/n a1="<<a1<<" a2="<<a2. public: D():B().a2=a2_.int b1_):A(a1_.c2=0.d2.} void afis1() {std::cout<<"/n b1="<<b1<<" b2="<<b2. class DER12: public DER1. Acesta constă în declararea clasei BAZA ca fiind clasa de bază virtuală. public: B():A() {b1=0.0) {b1=b1_. public DER2 {}. class B: public virtual A {int b1.

Funcţiile din cadrul unei clase se pot clasifica în: . Utilizarea constructorilor 2. fără argumente şi de tip public.  O clasă are un singur destructor.funcţii de tip prieten (friend).destructori.  Destructorul are acelaşi nume cu al clasei şi se declară cu operatorul ~ inainte. . . . ei se deosebesc prin numărul şi tipul argumentelor.  Destructorii sunt apelaţi automat înaintea eliberării memoriei alocată automatic sau static pentru datele membru. Dacă utilizatorul declară cel puţin un constructor atunci compilatorul nu mai generează acest constructor implicit.funcţii virtuale.constructori. Utilizarea destructorilor 3.  Utilizatorul nu va putea apela explicit destructorul unei clase. .  Funcţia constructor are acelaşi nume cu al clasei (case sensitive).  Destructorul nu preia şi nu întoarce valori. automatic sau dinamic. creare de tip static. .  In cazul în care nu se scrie nici un constructor se va apela automat un constructor.4 CONSTRUCTORI ŞI DESTRUCTORI Scop: 1. Înţelegerea ordinii de apel a destructorilor Consideraţii teoretice: CONSTRUCTORI:  Constructorul se apelează automat la crearea fiecărui obiect al clasei.  Există şi un constructor implicit de copiere ce iniţializează obiectul curent cu datele (membrii) din alt obiect de acelaşi tip (aparţinând aceleiaşi clase) El are forma nume_clasă(nume_clasa &)şi poate fi redefinit.  In cazul în care nu este declarat nici un destructor se va apela unul implicit. .LABORATORUL NR.  Constructorii sunt apelaţi automat după ce se se alocă memorie (automatic sau static) pentru obiectele membru (date membru /membrii) DESTRUCTORI:  Destructorul este apelat automat când obiectul respectiv îşi încetează existenţa în memorie.funcţii statice. Înţegerea ordinii de apel a constructorilor 4.funcţii normale de acces.  O clasă poate avea mai mulţi constructuri. fie în exteriorul clasei prin utilizarea operatorului rezoluţie " :: ".  Constructorii nu întorc valori. Explicitarea funcţiilor membre (inclusiv a constructorilor şi destructorilor) se poate face fie în interiorul declaraţiei clasei.

afis_a().h> #include <iostream> using namespace std. //cout<<"\n constructor B3(a1.int b1_. int b1_):A3(a1_) {b1=b1_.4.b2=0.int a3_) {a1=a1_. B3 z(1.5. return 0.funcţii de tipul operator. z. } Exemplu: #include <stdio. char **argv) { //A3 x(4). Exemplu: #include <stdio.int b2_. class A3 { public: int a1. B3(int a1_.a2=a2_.2.} void afis_a() {cout<<"\nClass A3: a1="<<a1<<" a2="<<a2<<" a3="<<a3.//cout<<"\n constructor A3(a1)<<a1:"<<a1. cout<<" b1="<<b1<<" b2="<<b2<<" b3="<<b3.afis_b().a2_.b3=b3_. int main(int argc. //B3 y(2. public: int b1.3.b3=0. .h> using namespace std. //z.int a3_. //y. getchar().} }. private: int a3.afis_b()..int b3_):A3(a1_.a2=0.int a2_.h> #include <iostream> #include <string. } A3(int a1_.} }.6).b2=b2_.a3=0.} void afis_b() {// cout<<"\nClass B3 a1="<<a3.b1)<<b1:"<<b1. public: A3(int a1_) { a1=a1_. //x.112) {b1=b1_. } B3(int a1_. protected: int b2. afis_a().int a2_.afis_a(). class B3:protected A3 {int b3.a3=a3_.7). protected: int a2.

} A::A(char* sir1) { strcpy(sir. if((sir=new char[dim])==NULL) cout<<"Memorie insuficienta". } class A1:public A { char *sir_ord_cresc. void prel(). }. dim=strlen(sir).dim*sizeof(char)). } void A::afis() { cout<<"\n Sirul este:"<<sir.sir). do{ for(i=1.i++) .ordonat=true. } void ordoneaza_cresc() {bool ordonat. scanf("%s". public: A1(unsigned long dim1):A(dim1) { sir_ord_cresc = new char[dim]. public: A(unsigned long dim1). unsigned long dim. memset(sir. } A::~A() { if(sir) delete[] sir.i<dim. } A1(char * sir1):A(sir1) {sir_ord_cresc = new char[dim].i<dim.} bool cauta_caracter(char x) { for(int i=0.int i.0. void afis(). ~A(). A::A(unsigned long dim1) { dim=dim1. A(char *). } void A::prel() { //cin>>sir.class A{ protected: char *sir. strcpy(sir_ord_cresc.sir1).i++) if(sir[i]==x) return true.this->sir). return false.

cin>>m. //x. //getchar(). return 0.} }while(!ordonat). char **argv) { A1 x(40).prel().afis().ordoneaza_cresc().afis(). sir_ord_cresc[i]=sir_ord_cresc[i-1]^sir_ord_cresc[i]. int main(int argc. } Desfăşurarea lucrării: 1. Se continuă cu exemplele corespunzătoare din secţiunea TESTE . Se rulează exemplul din secţiunea teoretică 2. x. /*void afis() { cout<<"\n Sirul ordonat este:"<<sir_ord_cresc. x. } if(sir_ord_cresc[i-1]>sir_ord_cresc[i]) { sir_ord_cresc[i-1]=sir_ord_cresc[i-1]^sir_ord_cresc[i]. x. ordonat=false. }*/ }. int m. sir_ord_cresc[i-1]=sir_ord_cresc[i-1]^sir_ord_cresc[i].

'l'. . 'd' ~P_ABC(). //'c' . . Daca constructorii nu ar fi declaraţi cu specificatorul de acces public nu am putea avea obiecte de tipul clasei respective în afara clasei.tip. Utilizarea modificatorilor de acces în cadrul constructorilor 3. Modificatorii de acces Specificatorul de acces din clasa de bază private protected public private protected public Exemplu //main.public: datele/membrele pot fi accesate de oriunde.h class P_ABC { protected: char *sir_c. short dim. Implicit toate datele şi metodele din cadrul unei clase sunt private. double *sir_d. chiar si din afara clasei. Utilizarea specificatorilor de acces. Înţelegerea noţiunilor de privite. long *sir_l. 4. protected şi public 2. Înţelegerea drepturilor de acces în condiţiile în care avem atât modificatori de acces cât şi specificatori de acces Consideraţii teoretice Datele (membrii) şi membrele (funcţiile) din interiorul unei clase pot avea următorii specificatori de acces: . . Modificator de acces private private private public public public Accesul moştenit de clasa derivată inaccesibil private private inaccesibil protected public Accesul din exterior inaccesibil inaccesibil inaccesibil inaccesibil inaccesibil accesibil P_ABC(short dim1.5 MODIFICATORII ŞI SPECIFICATORII DE ACCES Scop: 1. char tip1).LABORATORUL NR.protected: datele/membrele dintr-o clasă de bază pot fi vazute în interiorul claselor derivate dar nu şi în afara acestora.private: datele/membrele dintr-o clasă nu sunt văzute decât în interiorul clasei.

void afisare().} }.y.virtual void afisare()=0.int y1) {x=x1. class A : protected P_ABC { protected: //se pot apela in clasele derivate char *sir. //mostenire multipla class AZ: public A. long* obtine_sir(). protected: Z(int x1. void afisare(). class Z { int x. protected Z . void setare(int i. char* obtine_sir(). A(char*). class B : public P_ABC { protected: long *sir. virtual void citire()=0. long val) {sir[i]=val. void citire(). }. //functii virtuale pure ==> clasa de baza virtuala ==> NU se pot instanta direct obiecte ale acestei clase }.y=y1.} void citire(). }. ~A(). public: B(short dim1). public: //se pot apela in afara clasei si in afara ierarhiei de clase A(short dim1).

// if(sir_c==NULL &&) {cout<<"Memorie insuficienta".} sir=sir_c. if(tip=='d') sir_d=new double[dim]. sir // sir = new char[dim+1]. tip=tip1.h> #include <string.return. for(int i=0.h> #include <iostream> #include <main. }.sir_l=NULL.sir1). terminatorul de sir '/0' if(tip=='l') sir_l=new long[dim].} } P_ABC::~P_ABC() { if(sir_c) delete[] sir_c.'c') { //preia dimensiunea sirului //dim=dim1.{ public: AZ(short dim1.char valinit_c). } char* A::obtine_sir() {return sir. //if(!(sir= new char[dim])) {cout<<"Memorie insuficienta".'c') { //dim=strlen(sir1).i<dim.} // echivalent cu: if(!(sir= new char[dim])) {{cout<<"Memorie insuficienta". if(sir_d) delete[] sir_d. } A::A(short dim1):P_ABC(dim1.} sir=sir_c. } A::~A() { //if(sir) delete[] sir. //aloca memorie ptr.h> using namespace std. //main.sir_d=NULL.i++) sir[i]=sir1[i]. // +1 ptr. if(sir_l) delete[] sir_l.return.return. } A::A(char* sir1):P_ABC(strlen(sir1). // +1 ptr.} . P_ABC::P_ABC(short dim1. //strcpy(sir.} void A::afisare() {cout<<"\n Sirul din clasa A este:"<<sir.char tip1) { dim=dim1.cpp #include <stdio. terminatorul de sir '/0' // if(sir==NULL) {cout<<"Memorie insuficienta". sir_c=NULL. if(tip=='c') sir_c=new char[dim+1].return.

i++) sir[i]=valinit_c. char **argv) { A *s2. B *s3.char valinit_c):A(dim1). //s3->citire(). } Desfăşurarea lucrării: 1. s2->afisare().Z(2. int m. long valinit_l):A(5). eroare : clasa de baza abstracta -.i++) }*/ AZ::AZ(short dim1. //P_ABC d(4. s3->setare(0.afisare(). Se continuă cu exemplele corespunzătoare din secţiunea TESTE .'c').'k').3) { for(int i=0. s1.afisare().nu se vor instantia obiecte s2=new A("1234").B(9) { for(int i=0.'l') {sir=sir_l. s3->afisare(). s3=new B(2).} void B::afisare() {cout<<"\n Sirul din clasa B este:"<<sir[0].} void B::citire() { cin>>sir[0]. Se rulează exemplele din secţiunea teoretică 2.45).void A::citire() { cin>>sir.} B::B(short dim1):P_ABC(dim1.} /*AB::AB(char valinit_c. cin>>m. t. AZ t(5.s1("abcd").i<dim. } int main(int argc.} long* B::obtine_sir() {return sir.i<dim. //asteapta o tasta return 0.

O funcţie prieten. în totalitate. Cand se declară o data membru ca fiind static intr-o clasa. Înţelegerea tipului de dată friend pentru o clasă 2. Variabile Membru Statice Daca declaratia unei variabile membru este precedata de cuvantul-cheie static. Pentru a defini o variabila membru statica. se executa doar la momentul generarii unei instante). se stie. Atat functiile membru cat si datele membru (atributele) unei clase pot fi declarate static. Constructorii pot. În interiorul clasei este declarată cu cuvântul cheie friend în faţă. In C++ o functie membru statica se comporta asemanator cu o functie globala al carei domeniu este delimitat de clasa in care este definita. MEMBRII STATICI Un tip aparte de membri ai unei clase sunt membrii statici. . ea se declară prin scrierea cuvântului cheie friend înaintea declararaţiei propiu-zise a funcţiei. Variabilele statice (ca si functiile membru statice de altfel) pot fi utilizate indiferent daca exista sau nu instante ale clasei respective. ea nu este înca alocată. sa modifice valorile variabilelor statice (de exemplu. acest lucru se realizează în exteriorul clasei. este o funcţie declarată în afara clasei (nu aparţine clasei) şi căreia i se dă acces la toate datele din cadrul clasei. În interiorul clasei. Variabilele membru statice sunt folosite cel mai adesea pentru a asigura controlul accesului la o resursa comuna (ex. Prin declarare nu se aloca memorie. Adresa obiectului curent este dată de operatorul this. Accesarea unei variabile statice se face folosind numele clasei si operatorul de specificare a domeniului ("::"). Spre deosebire de variabilele membru obisnuite. pentru a contoriza numarul instantelor unei clase. Înţelegerea tipului de dată static pentru membrii unei clase 3. Functii Membru Statice Si functiile membru pot fi declarate ca statice. insa. Operatorul "this" Cuvântul cheie this arată adresa obiectului curent (în care ne aflăm) iar *this este valoarea obiectului curent. initializarea unei variabile statice NU poate cadea in sarcina constructorilor clasei (constructorii. create la executia unui program).6 DATE ŞI FUNCŢII DE TIP FRIEND ŞI STATICE Scop: 1. pentru variabilele statice nu sunt create copii individuale ale acestora pentru fiecare obiect in parte. atunci va exista o copie unica a acelei variabile care va fi folosita in comun de catre toate obiectele instantiate din clasa respectiva. De aceea. Acest tip de variabile se mai folosesc si pentru a stoca informatii comune unei intregi clase de obiecte.LABORATORUL NR. scrierea intr-un fisier). aceasta trebuie prevazuta cu o definire globala undeva in afara clasei. O clasă ale cărei funcţii sunt. friend pentru altă clasă se numesţe clasă prietenă a acelei clase. Utilizarea instanţierii claselor cu metode statice Consideraţii teoretice: Funcţii de tipul "prieten" (friend) O funcţie de tip friend (prieten) este o funcţie care nu este membră a clasei şi are acces la toţi membrii clasei.

} A(int a1_) {a1=a1_. return 0. friend void aduna(A& x1.h> #include <iostream> // definim variabila cnt pentru a contoriza numarul de obiecte de tip A existente class A { int a1. rez=x1. A() {a1=0. cnt++.} A(int a1_) {a1=a1_. //aici se declara cnt -. std::cin>>m.a1+x2. int m.//functii friend #include <stdio.t). std::cout<<"\n1:". aduna(s.//vector cu 10 obiecte de tip A.h> #include <iostream> class A {int a1.a1. public: A() {a1=0. int m. A& x2) { int rez. } //variabile de tip static #include <stdio.} }. z(4). void aduna(A& x1. std::cout<<"\n x1.cnt++. } std::cout<<"\n2:".} ~A() {cnt--. } Desfăşurarea lucrării: 1.} static void afis() {std::cout<<"\n nr.variabila nu se afla in obiectele instantiate int main() { A x[10]. A::afis(). } int main(int argc. Se continuă cu exemplele corespunzătoare din secţiunea TESTE .obiecte:"<<cnt. instantiate cu constructorul implicit () { A y[5].} }. std::cin>>m. A::afis(). int A::cnt=0. Se rulează exemplele din secţiunea teoretică 2. public: static int cnt. char **argv) { A s(3).a1="<<rez.a1 +x2. return 0.t(5). A& x2).

LABORATORUL NR. Prin acest pointer putem avea acces doar la membrii clasei derivate care au fost moşteniţi de la clasa de bază. Utilizarea funcşiilor virtuale Consideraţii teoretice: Funcţiile virtuale sunt folosite pentru implementarea obiectelor polimorfice. care se declară în interiorul unei clase de bază şi se redefineşte (modifică) în clasele derivate. ţinând cont de tipul obiectului (care clasă) la care punctează acel pointer. ea nerealizând nimic concret. mai multe metode". Când un pointer al clasei de bază punctează la o funcţie virtuală din clasa derivată. Obiectele polimorfice se careacterizează prin faptul că folosind aceeaşi formă de apel pentru funcţiile membre realizăm operaţii diferite. Înţelegerea noţiunii de polimorfism 2. compilatorul determină care versiune (care din codurile/ care explicitare) a funcţiei trebuie apelată. //polimorfism #include <stdio. care pune în evidenţă "poli morfism-ul" Variabile de tip pointer care punctează la clasele derivate Presupunem două clase. şi aceasta este apelată prin intermediul acestui pointer. Pentru a crea o funcţie virtuală. Clasele abstracte sunt utilizate doar pentru a fi moştenite. ea fiind declarată doar pentru ca în clasele derivate să fie declarată şi explicitată. // p preia adresa lui OB_TIP_BAZA // p poate puncta la obiecte derivate p=&OB_TIP_DER. invers nu este valabil. denumite:BAZA şi DERIVATA. Funcţiile viruale implementează filozofia "o singură interfaţă. Nu se pot intanţia obiecte pentru clase abstracte. . O clasă ce conţine o funcţie virtuală pură se numeşte clasă abstractă. În aceste condiţii. următoarele instrucţiuni sunt valabile: BAZA *p. trebuie să utilizăm cuvântul cheie virtual. La nivelul fiecărei clase funcţiile virtuale împlementează cod specific clasei respective. // p preia adresa lui OB_TIP_DER Un pointer al clasei de bază poate puncta la un obiect din clasa derivată. aceeaşi listă de parametrii şi întorc aceelaşi tip de dată. unde clasa DERIVATA moşteneşte clasa BAZA.7 POLIMORFISM. FUNCŢII VIRTUALE Scop: 1. Sintaxa pentru o funcţie virtuală pură este: virtual tip nume_funcţie(listă_de_parametri)=0.h> #include <iostream> using namespace std. Adică tipul obiectului (clasa ) la care punctează determină versiunea funcţiei virtuale care va fi executată. //un obiect de tip BAZA DERIVATA OB_TIP_DER. Funcţii virtuale O funcţie virtuală este o funcţie membră a unei clase. // un obiect de tip DERIVATA // pointer-ul p poate puncta (prelua adresa) la obiecte de tip BAZA p=&OB_TIP_BAZA. // pointer-ul care punctează la clasa baza BAZA OB_TIP_BAZA. fără cod/explicitare se numeşte funcţie virtuală pură. O astfel de funcţie virtuală. însă ele au acelaşi nume. fără a genera vreo eroare. O funcţie virtuală poate fi declarată şi numai formal. înainte de declaraţia funcţiei.

l1.l2) {} double perimetru() { return 2*(laturi[0]+laturi[1]).0) : Patrulater(l1.l2. cout<<"\n "<<perim.i++) { double perim.1.5. } virtual double arie() {}.0. elem = *(++colectie)) printf("\n %f". char **argv) { Patrulater *colectiePatrulatere[10].0) : Patrulater(l1.0.0. vector de pointeri void CalculeazaPerimetre(Patrulater *colectie[]) {// for-ul se executa atata timp cat elem != NULL // elem este un pointer de parcurgere de tip Patrulater // la fiecare iteratie se trece la adresa urmatoare for(Patrulater *elem = *colectie.l1.4). colectiePatrulatere[i++] = new Dreptunghi(6. } }. class Dreptunghi : public Patrulater { public: Dreptunghi(double l1=0.// sau printf("\n %f". colectiePatrulatere[i++] = new Dreptunghi(2. double l3=0. colectiePatrulatere[i++] = 0. colectiePatrulatere[i++] = new Patrulater(2.3.2). laturi[3] = l4. //CalculeazaPerimetre(colectiePatrulatere). }.figuri_geom[i]!=NULL. } }.//vector cu 10 adrese la obiecte de tip Patrulater int i = 0.0. laturi[2] = l3. double l4=0. .1.5).0) {laturi[0] = l1.0.perimetru()).5). double l2=0.0. (*elem). class Patrat : public Patrulater { public: Patrat(double l1 = 0.7.l1) {} double perimetru() { return 4*laturi[0].0.l1. perim = figuri_geom[i]->perimetru().class Patrulater { protected: double laturi[4]. } double arie() { return laturi[0]*laturi[0]. colectiePatrulatere[i++] = new Patrat(6. double l2=0.3). prima scriere este sugestiva ptr.7. colectiePatrulatere[i++] = new Dreptunghi(2. laturi[1] = l2. elem->perimetru()). public: Patrulater(double l1=0. } } int main(int argc. } double arie() { return laturi[0]* laturi[1]. } virtual double perimetru() { return laturi[0]+ laturi[1]+laturi[2]+laturi[3].0. elem . // *colectie[] === **colectie. } //se procedeaza idem si pentru arie void afis_si_calc_perim(Patrulater *figuri_geom[]) { for(int i=0.

Se continuă cu exemplele corespunzătoare din secţiunea TESTE . return 0.cin>>m. Se rulează exemplele din secţiunea teoretică 2. } Desfăşurarea lucrării: 1. int m.//sau afis_si_calc_perim(colectiePatrulatere).

Nu este posibila definirea unui operator care sa ia ca parametri exclusiv pointeri (exceptand operatorii: = & ." :: " . Restricţii privind supraîncărcarea operatorilor: .operator op (obiect 2) nemembră obiect1 op obiect2 operator op (obiect1. obiect2) b)Pentru operatorul unar "op" avem: Funcţia Sintaxa formei de apel externe op obiect1 membră a clasei obiect1 op op obiect1 nemembră obiect1 op Sintaxa formei interne (canonice) de apel obiect1.nu pot fi supraîncărcaţi decât operatorii existenţi.operator op () operator op (obiect1) operator op (obiect1) #include <stdio.se păstrează precedenţa operatorilor operator (nu exista posibilitatea de a determina. " () ". . . public: //constructor declarat şi explicitat în interiorul declaraţiei clasei VECT() .Un operator trebuie ori sa fie membru al unei clase. .operator op () obiect1.operatorii: " ." -> " funcţia operator trebuie să fie membră nestatică a clasei.h> #include <iostream> //supaincarcarea operatorilor class VECT { double v[3].). ." [] ". ca "+" sa fie prioritar fata de "/"). . .* ".operatorii binari vor fi supraîncărcaţi doar ca operatori binari. .pentru operatorii : " = "." .LABORATORUL NR. ". de exemplu. De la aceasta regula fac exceptie doar operatorii new si delete.operatorii unari vor fi supraîncărcaţi doar ca operatori unari.8 SUPRAÎNCĂRCAREA OPERATORILOR Scop: 1. " ?: " şi " sizeof " nu pot fi supraîncărcaţi. ori sa aiba cel putin un parametru de tip clasa.Nu se poate modifica numarul operanzilor preluati de un operator (dar se poate ignora unul din parametri). a)Pentru operatorul binar "op" avem: ( op poate fi unul din operatorii din lista cu operatori C++) Funcţia Sintaxa formei de apel externe Sintaxa formei interne (canonice) de apel membră a clasei obiect1 op obiect2 obiect1. Utilizarea supraîncărcarii operatorilor prin utilizarea funcţiilor friend 2. Utilizarea supraîncărcarii operatorilor fără a utiliza funcţiile friend Consideraţii teoretice: Supraîncărcarea operatorilor (overloading-ul) presupune redefinirea operatorilor cu ajutorul funcţiei de tipul operator.

v[1]=y. double z) { v[0]=x. } //operatoru de atribuire X = Y VECT VECT::operator=(VECT w) { v[0]=w.v[2]=z.v[0].v[2]+ w2. //friend void operator |=(VECT&.this) //ADUNAREA A+=B VECT operator +=(VECT). v[1]=0.VECT).B).\n v[2]=%f".\n v[1]=%f. //C=operator+(A.v[0].VECT&). //X=-X VECT operator-().v[1]. --. v[2]=w. elem.} ~VECT(){}//desctructor //declaraţie constructor cu 3 argumente VECT(double x1.} void VECT::afiseaza() { printf("\n Valorile: v[0]=%f. //C=B.v[2].operator^(A). operator + este funcţie externă clasei VECT operator+(VECT w1. } // X = W1 + W2 .v[2]=w.VECT w2) { VECT elem. //VECT(VECT&). //ADUNAREA C=A+B friend VECT operator+(VECT. elem.v[0].v[2]).v[0]=w1.v[1]+w2. DE //EXEMPLU pentru efectuarea ADUNAREA (adica de fapt X=W1+W2) .double y.double x3).v[1]=w. }.v[2]=w1.C=B+A ( B --. //double& operator[](int). return elem. operator ^ este membră a clasei şi o vom utiliza.VECT&).double x2.v[1]. // explicitare constructor VECT::VECT(double x. v[2]=0. friend VECT operator ^=(VECT&.v[2]. --.v[0]+w2. } //explicitare constructor copiere //VECT::VECT(VECT &w) //{ v[0]=w.C=A+B VECT operator^(VECT). //sau friend VECT operator!(VECT).v[0]. return *this. //friend bool operator==(VECT. } // X = W1 ^ W2 .v[1].//constructor de copiere //operatorul atribuire VECT operator=(VECT).v[1].VECT).{ v[0]=0. //void operator *=(VECT).v[2]. v[1]=w. elem. void afiseaza().v[1]=w1.

v[1].v[1].v[2]+ w2. } /* void operator|=(VECT &w1.v[1].v[0].-u. atribuire /* VECT x(1. elem.v[1]=w1.v[2]=w1.v[1]+w2. } /* void VECT::operator*=(VECT w) { v[0]=v[0] + w. return elem.v[2].y. w1. return elem.v[2]+ w2. v[2]=v[2] + w.2.v[0]+w2.v[2].//unde W1 este obiectul curent (*this) VECT VECT::operator^(VECT w) // w=W2 { VECT elem. v[1]=v[1] + w. elem. } VECT operator!(VECT u) { VECT elem(-u.v[0]+w2.v[0]=w1. return w1.-u.-v[2]). return *this.v[0]. } //X+=Y VECT VECT::operator+=(VECT w) { v[0]=v[0] + w.v[0]=v[0] + w.v[2].v[1]=w1. VECT& w2) { w1. w1.v[1].3). w1. . VECT& w2) { w1.v[2]=w1.v[1]+w2. } int main(int argc.v[0]. elem.v[0]. }*/ VECT operator^=(VECT &w1.v[0]=w1. }*/ // X = -X VECT VECT:: operator-() { VECT elem(-v[0].v[1]=v[1] + w.v[0]. return elem.v[1]. w1.v[1].v[2].v[2]=v[2] + w. char **argv) { //vf.-v[1]. v[2]=v[2] + w.v[0].v[2]. v[1]=v[1] + w.v[2]).

//constructor de copiere //operatorul atribuire VECT operator=(VECT).z. int m.afiseaza().-6.11.y(10. //x|=y.2.z.afiseaza(). v[2]=0.y(10. std::cin>>m.afiseaza().300). x+=y. return 0. VECT x(1.y).operator ^(y).afiseaza().12).12). //z=x^y.3). adunare ^ si atribuire VECT x(100.double x2. //sau //z=x.9).int m. std::cin>>m. //z.afiseaza(). // z=x+y. std::cin>>m. public: //constructor declarat şi explicitat în interiorul declaraţiei clasei VECT() { v[0]=0.afiseaza().11.3). v[1]=0.return 0. */ /*VECT s(3.-6. return 0.200.2.afiseaza(). s=!s. */ //vf adunare + si atribuire // VECT x(1. //vf.y(10. //VECT(VECT&).12). s. s=-s. s.11. } Exemplu: #include <stdio.double x3).} ~VECT(){}//desctructor //declaraţie constructor cu 3 argumente VECT(double x1. //supraincarcarea operatorului "identic" . //operator indexare double& operator[](int). // z.9). y. //vf operator unar // /*VECT s(3. int m. //x^=y.y=x. x. //sau // z=operator+(x.h> #include <iostream> */ //supaincarcarea operatorilor class VECT { double v[3]. // y.

double z) { v[0]=x.v[2]). return false.v[0] && A.v[0]. } double& VECT::operator[](int i) { return v[i].afiseaza(). bool operator<(VECT).\n v[2]=%f".v[1]. // b=x==y.v[0] && v[1]==A.11.v[1] && A.friend bool operator==(VECT.v[1]. char **argv) { VECT x(10.v[1]==B.} void VECT::afiseaza() { printf("\n Valorile: v[0]=%f. return false.y(10. v[2]=w.\n v[1]=%f.v[0]==B.v[2]. return *this. } bool VECT::operator<=(VECT& A) { if(v[0]==A.v[2]) return true.12). } //explicitare constructor copiere //VECT::VECT(VECT &w) //{ v[0]=w.v[2]==B.v[1] && v[2]==A.v[2]=w.12). v[1]=w.v[2]) //this.y).v[0] && v[1]==A. VECT B) {if(A. } bool VECT::operator<(VECT A) { if(v[0]==A. } //operatoru de atribuire X = Y VECT VECT::operator=(VECT w) { v[0]=w.v[0].double y.v[2]) return true. bool b. }.v[1]=y. .v[0] este echivalent cu v[0] return true. // x. } int main(int argc.v[1]=w. // b=operator==(x.//semnificatie schimbata in identic bool operator<=(VECT&).v[1]. } bool operator==(VECT A. return false.v[0].11.v[2].v[2]=z.//semnificatie schimbata in identic void afiseaza().v[1] && v[2]==A.VECT). // explicitare constructor VECT::VECT(double x.

v[1]=0. return *this.h> #include <iostream> //supaincarcarea operatorilor class VECT { double v[3]. else printf("diferite").v[0]. } Exemplu: #include <stdio.v[2]). std::cin>>m.v[0]. // explicitare constructor VECT::VECT(double x. public: //constructor declarat şi explicitat în interiorul declaraţiei clasei VECT() { v[0]=0. v[2]=0.operator<(y). double z) { v[0]=x.\n v[2]=%f". */ int m. .v[2]. s=x[0].//constructor de copiere //operatorul atribuire VECT operator=(VECT). /* double s. }. //VECT(VECT&). //semnificate de identitate (==) b=x<=y.s).v[1]. } //operatorul de atribuire X = Y VECT VECT::operator=(VECT w) { v[0]=w.\n v[1]=%f.v[0]. //semnificate de identitate (==) if(b) printf("identice").v[2]=z.double x2. //operator indexare char* operator[](int). v[2]=w.v[2]=w.double y. } //explicitare constructor copiere //VECT::VECT(VECT &w) //{ v[0]=w.v[1].// b=x.double x3). printf("x[0]:%f". v[1]=w.v[1]=w. } char* VECT::operator[](int i) {char* den. // b=x<y.v[1].} void VECT::afiseaza() { printf("\n Valorile: v[0]=%f.} ~VECT(){}//desctructor //declaraţie constructor cu 3 argumente VECT(double x1.return 0. void afiseaza().h> #include <string.v[2].v[1]=y.

"luni"). "marti").").break.y(10. Se rulează exemplele din secţiunea teoretică 2. } int main(int argc. case 4: strcpy(den.den=new char[10].break. int m. } Desfăşurarea lucrării: 1. printf("Denumirea:1:%s". char **argv) { VECT x(10. std::cin>>m.zi).break."joi"). switch(i) { case 1: strcpy(den. case 2: strcpy(den.12).11. zi=x[10].12). bool b. } return den. default: strcpy(den.11.return 0.afiseaza(). // x."zi inc. Se continuă cu exemplele corespunzătoare din secţiunea TESTE . char *zi.

neutilizand buffer-e. • clasa fstream ofera metode pentru operatii cu fisiere.LABORATORUL NR. int m. Exemplu: #include <stdio.iesire. Utilizarea obiectelor standard din cadrul claselor I/O Consideraţii teoretice: Stream-urile au in principal rolul de a abstractiza operatiile de intrare. sunt create si initializate automat patru obiecte: • • • cin gestioneaza intrarea de la intrarea standard (tastatura). • clasa ios este clasa de baza pentru clasele de stream-uri de intrare si de iesire.9 FLUXURI DE INTRARE/IEŞIRE. class A{ static int d.h> #include <iostream> #include <iomanip> using namespace std. sub libraria standard iostream. public: . Ele ofera metode de scriere si citire a datelor independente de dispozitivul I/O si chiar independente de platforma. cerr gestioneaza iesirea catre dispozitivul standard de eroare (ecranul). Obiecte standard Cand un program C++ care include iostream. In C++ stream-urile au fost implementate utilizand clase. double t. dupa cum urmeaza: • clasa streambuf gestioneaza buffer-ele. OBIECTE STANDARD Scop: 1. Stream-urile incapsuleaza (ascund) problemele specifice dispozitivului cu care se lucreaza. • clasele istream si ostream sunt derivate din ios • clasa iostream este derivata din istream si ostream si ofera metode pentru lucrul cu dispozitivul standard de intrare/iesire . Înţelegerea noţiunii de flux I/O 2. Clasa ios are ca variabila membru un obiect de tip streambuf.h este lansat in executie. cout gestioneaza iesirea catre iesirea standard (ecranul).

cout<<"t2="<<t<<endl. //std::cout<<"TEST". cout<<"t3="<<t<<endl. cout<<"m[hexa]="<<hex<<m<<endl. cout. int A::d=8."<<endl. cout<<"t1="<<t<<endl. t=5. cout.precision(4). cout<<setprecision(5)<<"t4="<<t<<endl. Se continuă cu exemplele corespunzătoare din secţiunea TESTE .precision(12). cout<<"d="<<setw(7)<<setfill('_')<<d<<endl. //int m.afis(). // pe post de asteapta o tasta } Desfăşurarea lucrării: 1. x. Se rulează exemplele din secţiunea teoretică 2. cout.1234567. } void afis() { //umple spatiul liber pana la dimensiunea data de setw(dim) cu caracterul specificat cout<<setfill('*')<<"m="<<setw(6)<<setfill('*')<<m<<". } }. char **argv) { A x.A(){m=11. //se declara ca variabila globala int main(int argc. std::cin>>m.precision(2).

fis1<<15<<" "<<13. aplicatiile trebuie sa includa fstream. //deschidere fişier text. citire if (!fis2){cout<<"Eroare la deschiderea fis. ifstream fis2(numefis). Pentru a le utiliza. return 1.h. fara trunchiere fisier if (!fis1){ cout<<"Eroare la dechiderea fişierului!\n". int main(int argc. } }. fis1.close().h> <iostream> <iomanip> <fstream> using namespace std. int b[3]. . fis1<<"ABCD ".10 FLUXURI DE INTRARE/IEŞIRE. citire!\n".txt //ofstream fis1(numefis.close(). ptr. //adauga.} fis1<<"A111 B222 ".scrie_in_Fisier("test24. OPERATII DE INTRARE/IESIRE CU FISIERE Scop: Realizarea operaţiilor cu fişiere utilizând fluxurile I/O Consideraţii teoretice: Lucrul cu fisiere se face prin intermediul clasei ifstream pentru citire respectiv ofstream pentru scriere. //deschiderea fis. x. ptr.return 1.txt"). Clasele ofstream si ifstream sunt derivate din clasa iostream. } int citeste_din_Fisier(char* numefis) { char a[3][100]. ca urmare toti operatorii si toate functiile descrise mai sus sunt mostenite si de aceasta clasa. fis2. char **argv) { A x.LABORATORUL NR. cout<<"a[0]:"<<a[0]<<" a[1]:"<<a[1]<<" a[2]:"<<a[2]<<" b[0]:"<<b[0]<<" b[1]:"<<b[1]<<endl.ios::app|ios::out). la sfarsit. Exemplu: #include #include #include #include <stdio. // FISIERE TEXT class A{ public: int scrie_in_Fisier(char* numefis) { ofstream fis1(numefis).} fis2>>a[0]>>a[1]>>a[2]>>b[0]>>b[1].

return 0. Se rulează exemplele din secţiunea teoretică 2. } Desfăşurarea lucrării: 1. Se continuă cu exemplele corespunzătoare din secţiunea TESTE .x.citeste_din_Fisier("test24.txt").

putem proceda ca în exemplul următor: #include <iostream. Ca urmare este necesară anticiparea unor posibile excepţii. cout << "b= ".LABORATORUL NR. } cout << "\n". în vederea tratării acesteia. c = a / b. de operaţii nepermise. Pentru particularizarea tratării erorii. catch { bloc ce se execută în cazul în care apare o excepţie/eroare } Acest cuvânt cheie este urmat. return 0. între acolade. de blocul ce se execută în cazul unei excepţii/erori throw transmite excepţia. int main() { int a.cin >> b. } catch() { cout<<”b este zero”. de contori în afara limitelor admise. catch şi throw.h> int main() . Cuvântul cheie try este urmat de blocul ce se execută şi care poate genera o eroare în execuţie try { bloc ce se execută în mod normal} Acest cuvânt cheie permite aplicaţiei să anticipeze un comportament anormal şi va încerca să se ocupe de ea.c. C + + oferă trei cuvinte cheie pentru a gestiona o excepţie: try . către sistemul de operare. } Cele trei puncte din argumentul catch semnifică faptul că vor fi tratate toate excepţiile.11 TRATAREA EXCEPŢIILOR Scop: Implementarea metodelor de control a posibilelor erori din cadrul unei aplicaţii Consideraţii teoretice: În timpul executării unui program pot apărea situaţii în care sunt generate erori datorate de multe ori depăşirii puterii de reprezentare a numerelor. etc. cin >> a. de multe ori provenite de la preluarea incorectă a datelor.b. Ex: #include <iostream> using namespace std. cout << "a= ". try { if( b==0 ) throw.

} cout << "\n". } cout << "\n". try { cout << "b= ".c. c=a/b+a/(b-1)+a/(b-2). cin >> b.b. return 0. Se continuă cu exemplele corespunzătoare din secţiunea TESTE . cout << "a= ". } catch(const int Message) { cout << "Error:b=1”. if(b == 1) throw 1.b. if(b == 0) throw "b este ZERO !". cin >> a. c = a / b. } Desfăşurarea lucrării: 1.h> int main() { int a. cin >> a. cout << "a= ". return 0. } catch(const char Message) { cout << "Error: b=2". catch(const char* Message) { cout << "Error: b=0”. try { cout << "b= ". } În cazul în care sunt tratate mai multe excepţii putem avea: try { // codul ce poate contine exceptii/erori } catch(Arg1) { //tratarea primei excetii } catch(Arg2) { //tratarea urmatoarei exceptii } Deosebirea între argumente se va face prin tipurile acestora Ex: #include <iostream.{ int a. } catch(const char* Message) { cout << "Error: " << Message.c. cin >> b. if(b == 2) throw '2'. if(b == 0) throw "b este ZERO !". Se rulează exemplele din secţiunea teoretică 2.

} Clasa wxFile este utilizată pentru lucrul cu fişiere #include <wx/file.h> int main(int argc.Len()).a). str. wxString str. Se continuă cu exemplele corespunzătoare din secţiunea TESTE .IsOpened()) wxPuts(wxT("Fisierul este deschis")). if (!file.h> int main(int argc.12 UTILIZAREA CLASELOR WXWIDGETS (I) Scop: Familiarizarea cu uneltele de dezvoltare a interfeţelor grafice Consideraţii teoretice: Clasele wxWidgets se constituie într-un se de instrumente C++ ce permit crearea de interfaţe grafice GUI (Graphical User Interface) în C++.\n"). Se rulează exemplele din secţiunea teoretică 2. char **argv) { wxString str1 = wxT("Un")."). char **argv) { int a = 10.h> int main(int argc. } Formatarea şirurilor #include <wx/string. aplicaţiile wxWidgets pot rula pe toate sub toate sistemele de operare reprezentative: Linux. wxString str3 = wxT("exemplu. Aceste clase sunt open source şi cross-platform. wxFile file. Proiectul a fost demarat de către Julian inteligente în 1992.IsOpened()) wxPuts(wxT("Fisierul NU este deschis")). wxPrintf(wxT("Şirul are lungimea de %d caractere.LABORATORUL NR.Printf(wxT("a= %d\n". wxPuts(str). file. wxString str2 = wxT("prim"). str. #include <wx/string. if (file. Windows. wxPuts(str). Clasa wxString este utilizată pentru lucrul cu şirurile de caractere.Create(wxT("numefisier"). file. char **argv) { wxString str = wxT("Un sir de caractere. wxString str = str1 + wxT(" ") + str2 + wxT(" ") + str3.Close().Write(str). Unix si Mac. true). } Desfăşurarea lucrării: 1. file.\n").

} public: MainDialogBase( wxWindow* parent. const wxSize& size = wxSize( 400.wxwidgets. wxWindowID id = wxID_ANY.Skip(). const wxPoint& pos = wxDefaultPosition.h> #include <wx/colour.h> #include <wx/button. } virtual void OnCancelClick( wxCommandEvent& event ) { event.LABORATORUL NR.org) -.Skip().13 UTILIZAREA CLASELOR WXWIDGETS (II) Scop: Familiarizarea cu uneltele de dezvoltare a interfeţelor grafice Consideraţii teoretice: În vederea realizării interfeţelor grafice este necesară utilizarea metodelor (din cadrul claselor date) ce asigură gestiunea evenimentelor la nivel de aplicaţie.h> #include <wx/statline.h> #include <wx/gdicmn.Skip().h> #include <wx/settings. wxStdDialogButtonSizer* m_sdbSizer.h> #include <wx/font.h --wxWidgets license (www. Ex:Realizarea unui mic formular utilizând wxFormBuilder gui. } virtual void OnOKClick( wxCommandEvent& event ) { event.necesar înţegerii structurii claselor #ifndef __gui__ #define __gui__ #include <wx/intl.fişier generat de wxFormBuilder .300 ).h> #include <wx/sizer. wxButton* m_sdbSizerCancel. ~MainDialogBase().h> #include <wx/dialog.h> // Class MainDialogBase class MainDialogBase : public wxDialog { private: protected: wxStaticLine* m_staticLine. #endif //__gui__ . wxButton* m_sdbSizerOK. long style = wxCLOSE_BOX|wxDEFAULT_DIALOG_STYLE ). }. const wxString& title = _("wxMiniApp"). virtual void OnCloseDialog( wxCloseEvent& event ) { event.h> #include <wx/string.

this ).fişier generat de wxFormBuilder . 5 ). NULL. }. NULL.org) -. NULL. NULL. m_sdbSizerOK = new wxButton( this. m_sdbSizer = new wxStdDialogButtonSizer(). mainSizer = new wxBoxSizer( wxVERTICAL ).h" class MainApp : public wxApp { public: virtual bool OnInit(). wxLI_HORIZONTAL ). } MainDialogBase::~MainDialogBase() {// Eliberarea handler-ului de evenimente this->Disconnect( wxEVT_CLOSE_WINDOW. mainSizer->Add( m_staticLine. const wxSize& size. wxBoxSizer* mainSizer. m_sdbSizerOK->Connect( wxEVT_COMMAND_BUTTON_CLICKED. wxDefaultSize ). wxID_OK ). // conectarea handler-ului de evenimentelor this->Connect( wxEVT_CLOSE_WINDOW. wxCloseEventHandler( MainDialogBase::OnCloseDialog ) ). m_sdbSizerCancel->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED. this->SetSizer( mainSizer ). this ).h" MainDialogBase::MainDialogBase( wxWindow* parent. mainSizer->Add( m_sdbSizer. style ) { this->SetSizeHints( wxSize( -1.h #ifndef __main__ #define __main__ // main wxWidgets header file #include <wx/wx. . this->Layout(). 0.-1 ). wxID_ANY. wxEXPAND | wxALL. 5 ). wxID_CANCEL ). m_sdbSizer->Realize(). m_sdbSizerCancel->Connect( wxEVT_COMMAND_BUTTON_CLICKED. DECLARE_APP(MainApp) class MainDialog : public MainDialogBase { public: MainDialog( wxWindow *parent ). this ). wxEXPAND. pos.gui.necesar înţegerii structurii claselor #include "gui. m_sdbSizerOK->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED. this->Centre( wxBOTH ). wxDefaultSize. m_sdbSizer->AddButton( m_sdbSizerOK ). wxCommandEventHandler( MainDialogBase::OnCancelClick ). const wxString& title. this ). 5 ). m_sdbSizer->AddButton( m_sdbSizerCancel ). } main.wxWidgets license (www. wxCloseEventHandler( MainDialogBase::OnCloseDialog ) ). wxCommandEventHandler( MainDialogBase::OnOKClick ).h> // gui classes generated by wxFormBuilder #include "gui. m_staticLine = new wxStaticLine( this. wxWindowID id. m_sdbSizerCancel = new wxButton( this. size. long style ) : wxDialog( parent. const wxPoint& pos. id. title. wxDefaultPosition. wxCommandEventHandler( MainDialogBase::OnOKClick ).cpp . 0. wxCommandEventHandler( MainDialogBase::OnCancelClick ). 0. wxALIGN_RIGHT|wxBOTTOM|wxRIGHT.wxwidgets. 1. mainSizer->Add( 0.

Desfăşurarea lucrării: 1. virtual void OnCancelClick( wxCommandEvent& event ). virtual void OnOKClick( wxCommandEvent& event ). bool MainApp::OnInit() { SetTopWindow( new MainDialog( NULL ) ). Se compilează şi link-editează . Se lansează wxFormBuilder şi se construieşte interfaţa 2.cpp #include "main. } void MainDialog::OnOKClick(wxCommandEvent& event) { Destroy(). GetTopWindow()->Show(). #endif //__main__ main. return true. Se lansează CodeLite şi se adaugă metodele ce reprezintă răspunsul la evenimente 3. protected: virtual void OnCloseDialog( wxCloseEvent& event ).h" IMPLEMENT_APP(MainApp).virtual ~MainDialog(). } MainDialog::MainDialog(wxWindow *parent) : MainDialogBase( parent ) { } MainDialog::~MainDialog() { } void MainDialog::OnCloseDialog(wxCloseEvent& event) { Destroy(). } void MainDialog::OnCancelClick(wxCommandEvent& event) { } Destroy(). }.

B2 g2("g2". } invers?Explicaţi! C3(char *numevar1.4.delete h8. Este posiblil asignarea „d[2]=&m2”? Dar invers (m2=*d[2])? Explicaţi! class C3: protected A1 3.17. {B2 f6("f6"). } B2(char *numevar1. 3.} void C3::afis(char *str) {std::cout<<"C3#numevar:"<<numevar<<"-"<<str<< std::endl. } delete b2.5.} virtual void afis(char *str).*d[3]. strcpy(numevar.2.19).y1. . protected: int s2.4). C3 m2("m2".e[3].101. e[2]=m2. Este posiblil asignarea „d[0]=&w2”? Dar invers (w2=*d[0])? Explicaţi! 3.21. Este posiblil asignarea „d[1]=&g2”? Dar invers (g2=*d[1])? Explicaţi! 3. }.} C3 g7("g7").19).int x11. public: int t1.s1. B2 *h8=new B2("s5".x11. }. char* argv[]) {C3 a1[3]. {A1 c3("c3").6. public: B2():A1() {afis("CONSTRUCTOR_0"). } ~A1() {afis("DESTRUCTOR").int x11. void B2::afis(char *str) {std::cout<<"B2#numevar:"<<numevar<<"-"<<str<< std::endl. } A1(char *numevar1) {numevar=new char[100].y2.numevar1). Este posiblil asignarea „e[1]=g2”. A1() {numevar=new char[100]. afis("CONSTRUCTOR2"). strcpy(numevar. protected: int s1. } 3."N/A").*d4[2]. d[1]->afis("d[1]").32.x1.y1.t2. d[2]=&m2.int x11.afis("CONSTRUCTOR_2").int y11.y ale }. Ce se afişează în urma execuţiei ? int main(int argc.numevar1). void A1::afis(char *str) {std::cout<<"A1#numevar:"<<numevar<<"-"<<str<< std::endl.int s22): A1(numevar1. d[1]=&g2.afis("CONSTRUCTOR_2"). Adăugaţi codul necesar și în afara clasei.int s33): A1(numevar1.Se dă: int main(int argc.101. // return 0.t1.t3.LABORATORUL NR. } 2. char* argv[]) { A1 w2("d1".14 TESTE Scop: Testarea cunoştinţelor TEST#1 Se dau următoarele clase: #include <iostream> #include <stdio. d[2]->afis("d[2]"). afis("CONSTRUCTOR1").5.} void afis(char *str). b2=new C3("b2".delete[] numevar. Se dă o clasă ce conține coordonatele x.y11) { s2=s22. } invers?Explicaţi! ~C3() {afis("DESTRUCTOR"). } C3(char *numevar1):A1(numevar1) 3. *b2.h> #include <string.? Dar { int x3.17.} class B2: public A1 { int x2.21. // e[0]=w2.int y11. getchar().54).3. private: void calc(). } ~B2() {afis("DESTRUCTOR"). 4.5. Modificați clasa A1 astfel încât la fiecare apel al vreunui constructor sau al destructorului să afișeze numărul total al obiectelor instanțiate. Este posiblil asignarea „e[2]=m2”. } A1(char *numevar1. // d[0]->afis("d[0]"). // d[0]=&w2.32.54).e5("e5". invers? Explicaţi! public: C3():A1() {afis("CONSTRUCTOR_0"). return 0.strcpy(numevar.} //1.h> class A1 {int x1. protected: int s3.4).y1 3. afis("CONSTRUCTOR_0").1. } B2(char *numevar1):A1(numevar1) {afis("CONSTRUCTOR_1").y3.x11.? Dar 1) {s3=s33.} void afis(char *str). Este posiblil asignarea „e[0]=w2”.? Dar {afis("CONSTRUCTOR_1"). e[1]=g2. int y11) {numevar=new char[100]. protected:char *numevar.

4. protected: int s2. void B2::afis(char *str) {std::cout<<"B2#numevar:"<<numevar<<"-"<<str<< std::endl. }. private: void calc().numevar1).} virtual void afis(char *str).*d[3].x11.unui 4.y2.} void afis(char *str).4). Este posiblil asignarea „d[2]=&m2”? Dar invers (m2=*d[2])? Explicaţi! 3.y1.2.21.54).17.int x11. } ~A1() {afis("DESTRUCTOR"). e[2]=m2.h> class A1 {int x1.5. Este posiblil asignarea „d[1]=&g2”? Dar invers (g2=*d[1])? Explicaţi! 3.afis("CONSTRUCTOR_2").s1.h> #include <string.17.delete[] numevar.Se dă: int main(int argc. Este posiblil asignarea „e[1]=g2”.5. afis("CONSTRUCTOR2").19).1. } B2(char *numevar1.4). // return 0.} //1. char* argv[]) { A1 w2("d1". protected: int s1. } 4.y1.4. strcpy(numevar.2. C3():A1() {afis("CONSTRUCTOR_0"). două 4.afis("CONSTRUCTOR_2"). afis("CONSTRUCTOR_0"). } A1(char *numevar1.? Dar invers?Explicaţi! 3. } A1(char *numevar1) {numevar=new char[100]. Este posiblil asignarea „e[0]=w2”. int y11) {numevar=new char[100]. Modificați clasele astfel încât să contorizeze numărul obiectelor ce au utilizat la instanțiere constructori cu un singur parametru. // e[0]=w2. void A1::afis(char *str) {std::cout<<"A1#numevar:"<<numevar<<"-"<<str<< std::endl. Să se supraîncarce: conține coordonatele punctului Un operator pentru calculul distanței dintredistanței dintre cele două puncte. 3.} class B2: public A1 { int x2.t2. d[2]->afis("d[2]"). Este posiblil asignarea „e[2]=m2”. void C3::afis(char *str) {std::cout<<"C3#numevar:"<<numevar<<"-"<<str<< std::endl.6. Se dă o clasă ce conține coordonatele x. // d[0]=&w2. e[1]=g2.int x11. char* argv[]) {B2 a1("a1"). }.21.2. puncte.b2[2]. strcpy(numevar. class C3: protected A1 Să se supraîncarce: { int x3.19).int s22): A1(numevar1.d4("d4".t3. } intersecției a două obiecte.32. public: int t1.e[3]. C3(char *numevar1. // d[0]->afis("d[0]"). } ~B2() {afis("DESTRUCTOR").5. Este posiblil asignarea „d[0]=&w2”? Dar invers (w2=*d[0])? Explicaţi! 3. A1() {numevar=new char[100]. afis("CONSTRUCTOR1").int s33): A1(numevar1. Un operator pentru calculul ariei de public: intersecție a două obiecte.} void afis(char *str). B2 *g6=new C3("g6".y ale vârfurilor unui dreptunghi. public: B2():A1() {afis("CONSTRUCTOR_0").numevar1). d[2]=&m2. d[1]->afis("d[1]"). d[1]=&g2.y11) { s2=s22.int y11. Un operator ce întoarce un nou obiect ce C3(char *numevar1):A1(numevar1) conține vârfurile drepunghiului rezultat în urma {afis("CONSTRUCTOR_1"). Un operator ce întoarce un nou obiect ce la jumătatea TEST #2 Se dau următoarele clase: #include <iostream> #include <stdio. } ~C3() {afis("DESTRUCTOR"). {A1 c3.? Dar invers? Explicaţi! 3. } 2. }.x11. } } getchar().int x11.1.int y11. C3 m2("m2".101. Adăugaţi codul necesar și în afara clasei. } 3.y1 1) {s3=s33."N/A").3. {C3 f5("f5").y3.1. protected: int s3. protected:char *numevar. punct într-un plan. B2 g2("g2".? Dar invers?Explicaţi! 4. return 0.strcpy(numevar.x1.} .delete g6. } B2(char *numevar1):A1(numevar1) {afis("CONSTRUCTOR_1").t1. Ce se afişează în urma execuţiei ? int main(int argc.

strcpy(numevar.54). public: int t1.TEST #3 Se dau următoarele clase: #include <iostring> #include <stdio.1 d[2]=m2. }.y3.4).} void afis(char *str). //4. }.strcpy(numevar. d[1]=g2. 3.5. A1() {numevar=new char[100]. Este posiblil asignarea „d[1]=g2”.numevar1). void B2::afis(char *str) {std::cout<<"B2#numevar:"<<numevar<<"-"<<str<< std::endl.y2.101. t01=new C3("t01".numevar1).2 d[0]. afis("CONSTRUCTOR_1").} virtual void afis(char *str).x1. afis("CONSTRUCTOR1"). strcpy(numevar. public: B2(char *numevar1):A1(numevar1) {numevar=new char[100]. char* argv[]) {C3 *t01.afis("d[1]"). } ~C3() {afis("DESTRUCTOR").t1. C3 m2("m2".numevar1).r3("r3".x11.} A1(char *numevar1) {numevar=new char[100]. delete s5.h> #include <string. return 0. int y11) {numevar=new char[100]. {numevar=new char[100].d[3]. afis("CONSTRUCTOR2").32.? class C3: protected A1 Explicaţi! { char *numevar. }. strcpy(numevar. strcpy(numevar.} A1(char *numevar1.h> class A1 {int x1. getchar(). } ~B2() {afis("DESTRUCTOR"). În cazul în care este posibilă asignarea ce public: se afişează în urma apelului metodei C3(char *numevar1):A1(numevar1) afis(“d[i]”) .Se dă: int main(int argc.y11) { numevar=new char[100].int x11.19).21. char *numevar. int x3. } 3.//4.3 d[1]."N/A"). s3=s33.int s33): doi vectori cu numere de tip double si un A1(numevar1. } delete t01.int x11.delete[] numevar.s1.afis("d[0]").} ~A1() {afis("DESTRUCTOR").afis("d[2]").3 d[2]. afis("CONSTRUCTOR_0").21. return 0. afis("CONSTRUCTOR1").y1.//4. protected: int s3.t2. B2 g2("g2". int x2. char* argv[]) { A1 w2("d1". i=0.t3.32. pentru fiecare clasă în parte (adăugaţi direct pe codul scris şi rescrieţi numai metodele modificate).2. protected: int s2.} 1.19).int s22): A1(numevar1.3 getch(). . private: void calc(). Afişaţi acest număr în cadrul constructorilor şi destructorilor.101.numevar1).delete[] numevar. strcpy(numevar. 4.17.int x11.} strcpy(numevar.numevar1).*s5.afis("CONSTRUCTOR_2").y1. void C3::afis(char *str) {std::cout<<"C3#numevar:"<<numevar<<"-"<<str<< std::endl. s5=new B2("s5".} class B2: public A1 { char *numevar. Ce se afişează în urma execuţiei ? int main(int argc.// 4.1.? Explicaţi! 3.delete[] numevar. protected: int s1. Este posiblil asignarea „d[2]=m2”.5. 3.4).//4.x11. Adăugaţi câte un contor pentru numărul de obiecte instanţiate.y1 operator supaincarcat pentru operatia de ordonare 1) crescatoare a elementelor vectorului. s2=s22.54). } B2(char *numevar1.int y11. } R 2.numevar1).afis("CONSTRUCTOR2").1 sau 2 ? Explicaţi! {numevar=new char[100].d2[2].int y11.3. C3 q6("q6").17. {A1 y1("y1"). Sa se scrie o clasa ce contine un operator } supraîncarcat pentru operatia de concatenarea a C3(char *numevar1.} void afis(char *str). d[0]=w2. void A1::afis(char *str) {std::cout<<"A1#numevar:"<<numevar<<"-"<<str<< std::endl. B2 g4("g4").

.. protected: int s2...int x11. Să se supraîncarce: void afis(char *str).. { int x2.Se dă: ~A1() {afis("DESTRUCTOR")...} class A1 C3 g7("g7").} . Este posiblil asignarea „d[1]=&g2”? Dar ~B2() {afis("DESTRUCTOR"). {int x1. două puncte.....} int main(int argc.*d[3]..4.1..32..e5("e5".afis("CONSTRUCTOR_2"). B2 *h8=new B2("s5"..... 4. Un operator ce întoarce un nou obiect ce void C3::afis(char *str) conține coordonatele punctului la jumătatea {std::cout<<"C3#numevar:"<<numevar<<"-"<<str<< distanței dintre cele două puncte..int s33): invers?Explicaţi! A1(numevar1. strcpy(numevar. protected:char *numevar..19)..numevar1). Este posiblil asignarea „d[0]=&w2”? Dar {afis("CONSTRUCTOR_1").. afis("CONSTRUCTOR_0").21...x11.} unui punct într-un plan..y3.4).. {numevar=new char[100].....101. }.19).. void calc().. getchar().delete[] numevar. class B2: protected A1 d[0]->afis("d[0]").. d[1]->afis("d[1]"). {A1 c3("c3")..int x11..54). public: return 0.. 1) {s3=s33... }.54).delete h8. e[1]=g2...y ale ~C3() {afis("DESTRUCTOR").17. } invers (w2=*d[0])? Explicaţi! B2(char *numevar1.t2.. d[1]=&g2..? Dar C3(char *numevar1.. } 4.2.... Este posiblil asignarea „e[1]=g2”.? Dar invers? Explicaţi! class C3: public A1 { int x3... public: 3.t1.int y11.. {B2 f6("f6").3.h> //1.. protected: int s3. clasei.. } 3... } B2(char *numevar1):A1(numevar1) 3... } } A1(char *numevar1) R {numevar=new char[100].t3... apel al vreunui constructor sau al destructorului } să afișeze numărul total al obiectelor A1(char *numevar1.2. Este posiblil asignarea „d[2]=&m2”? Dar invers (m2=*d[2])? Explicaţi! void B2::afis(char *str) {std::cout<<"B2#numevar:"<<numevar<<"-"<<str<< std::endl. 2...17..} 3. { private: A1 w2("d1". char* argv[]) {C3 *a1.x1.... 4.5.x11.y11) { s2=s22.. } A1() delete b2. d[2]=&m2.y1. //. e[2]=m2..e[3].. } 3. std::endl. Se dă o clasă ce conține coordonatele x.. {std::cout<<"A1#numevar:"<<numevar<<"-"<<str<< //... char* argv[]) virtual void afis(char *str).. d[2]->afis("d[2]"). } C3(char *numevar1):A1(numevar1) {afis("CONSTRUCTOR_1").. return 0........1.5. b2[2]..*d4[2].} e[0]=w2..6.. int y11) instanțiate.. void A1::afis(char *str) d[0]=&w2... b2=new C3("b2".....5....32.. public: int t1..h> #include <string.."N/A").TEST #4 Se dau următoarele clase: #include <iostream> #include <stdio.numevar1)..int s22): A1(numevar1. } 3. strcpy(numevar. Un operator pentru calculul distanței dintre }. afis("CONSTRUCTOR2")..int y11...21.101.? Dar invers?Explicaţi! C3():A1() {afis("CONSTRUCTOR_0").s1. Ce se afişează în urma execuţiei ? int main(int argc.. 3.afis("CONSTRUCTOR_2")..y2.. //. Adăugaţi codul necesar și în afara {numevar=new char[100].. B2():A1() } {afis("CONSTRUCTOR_0")... Modificați clasa A1 astfel încât la fiecare afis("CONSTRUCTOR1").. C3 m2("m2"..... B2 g2("g2". Este posiblil asignarea „e[2]=m2”.strcpy(numevar..y1..y1 .. //. std::endl.4).int x11. protected: int s1. Este posiblil asignarea „e[0]=w2”.} invers (g2=*d[1])? Explicaţi! void afis(char *str).

.... } ........ } 2..t2....... {s3=s33.delete[] numevar. afis("CONSTRUCTOR_0")............ 3. } B2(char *numevar1.....m2...54).......m2. public: int t1.............afis("CONSTRUCTOR_2")...} virtual void afis(char *str). afis("CONSTRUCTOR2")..101.........19)......y3... R: .. strcpy(numevar.........5... getchar()..t1=e[0]...........x3=g2.4)... 6......19). int y11) {numevar=new char[100]. ... explicitarea A1(numevar1.m2... C3 m2("m2".y1.. e[0]..numevar1).1.... return 0.m2...................y11) { s2=s22.. R: ..........s1=5......TEST #5 Se dau următoarele clase: #include <iostream> #include <stdio.... } A1(char *numevar1....} class B2: protected A1 { int x2...s3=9............y1........ } A1(char *numevar1) {numevar=new char[100]............"N/A")........... char* argv[]) {A1 a1................ 2.....e[3].int y11.....} void afis(char *str)...... {B2 d4("d4”. } R int main(int argc....int x11......} ~C3() {afis("DESTRUCTOR")........int y11......int s22): A1(numevar1..x1.....x11..........21... } B2(char *numevar1):A1(numevar1) {afis("CONSTRUCTOR_1")... strcpy(numevar.int x11... private: void calc()...........s1.} void afis(char *str).g2......................... R: ..} B2 *b2=new B2("s5"......h> #include <string.......32. R: .. ....17.. 9...... 3....y2.. afis("CONSTRUCTOR1").... } ordonat crescător (se va scrie declaraţia clasei......w2............ ....... public: B2():A1() {afis("CONSTRUCTOR_0")....... } ~A1() {afis("DESTRUCTOR")...w2....... public: Să se supraîncarce un operator care să permită C3():A1() {afis("CONSTRUCTOR_0")....... .. 4..x1=9......t3. void A1::afis(char *str) {std::cout<<"A1#numevar:"<<numevar<<"-"<<str<< std::endl.m2....s1=9... void B2::afis(char *str) {std::cout<<"B2#numevar:"<<numevar<<"-"<<str<< std::endl. .... 10......... return 0.....t2.................. 8.. R: ................... R: ..........} //1..afis("CONSTRUCTOR_2")......int x11..... }..........t1. C3(char *numevar1...... .......h> class A1 {int x1..*c3[3]..... } } delete b2.strcpy(numevar....t2.....t1=9.21.s1.. .....................int s33): explicitarea unui constructor.......4).......t1=9.y1 1) destructorului şi explicitarea funcţiei operator).. R: .......*b2. char* argv[]) { A1 w2("d1"........ protected: int s2............Explicaţi dacă sunt sa nu posibile urmăroarele asignări: 1... } ~B2() {afis("DESTRUCTOR").g2.... public: int s3.. {C3 e5("e5").... ... Ce se afişează în urma execuţiei: int main(int argc.t1=g2...... B2 g2("g2"... A1() {numevar=new char[100]. pointer la un şir de numere de tip real)...t3=g2. }....... R: ............... }.... } obţinerea unui obiect având şirul de numere C3(char *numevar1):A1(numevar1) {afis("CONSTRUCTOR_1"). protected: int s1.2..x2....... Se dă o clasă ce gestionează elementele unui class C3: public A1 şir de caractere (această clasă va conţine un { int x3......17... protected:char *numevar...... void C3::afis(char *str) {std::cout<<"C3#numevar:"<<numevar<<"-"<<str<< std::endl...numevar1). 5.........x11.. 7..... R: ........ R: ...... ..

}. afis("CONSTRUCTOR_2"). {xc=0.int m1): A1(numevar1. } ~C3() {afis("DESTRUCTOR"). 3.} virtual void afis(char *str).strcpy(numevar.yc=t1.2.4. .10.. {A1 d1[2].. afis("CONSTRUCTOR_3").47).yb.1899.Este posibilă execuţia următoarelor instrucţiuni? Explicaţi de ce! 2.29).} 1.} void A1::tipar() {cout<<”xa=”<<setw(7)<<setfill('^')<<hex<<xa<<en dl.} ..} 2. void main() {B2 d1[2]. Se dă o clasă pentru gestiunea operaţiilor cu void afis(char *str).. } void A1::afis(char *str) {cout<<”A1_var:”<<numevar<<” tip:”<<str<<endl.x1) { xb=m1. a.51. C3 *a.} void B2::tipar() {cout<<setw(7)<<setfill('~')<<”xb=”<<hex<<xb<<en dl.h> {B2 g2("g2").} B2(char *numevar1. } A1(char*)..} {A1 *m[3]. d1[1].5.m[1]=&r2. 2. afis("CONSTRUCTOR_1"). void main() {A1 m[2]. m[0]=@a. } g1=new B2("g1".8. Ce se afişează în urma execuţiei ? } void B2::afis(char *str) {cout<<”B2_var:”<<numevar<<” tip:”<<str<<endl..46.int s1..y1) m[2]->tipar().} 2.} class B2: protected A1 { public:int xb.. int y1) {xa=x1... t1): A1(numevar1. } A1::A1(char *numevar1.. void main() {C3 a. . int). } class A1 {int g. 2.ya=0.. C3 *a.} {xc=s1. 2. void main() {A1 *m[2].. a=m[0]..} void afis(char *str).”N/A”).. d1[0].6. static int s. Ce se afişează în urma execuţiei ? int main() {C3 *m2. public:int xa. afis("CONSTRUCTOR_0”)....yc. getch().r1("var-r1".9.h=7. virtual void tipar().. Să se supraîncarce un operator care să permită adunare cu un anumit număr de ore (se va scrie declaraţia clasei. afis("CONSTRUCTOR_1").. A1() {xa=0.xa=1..} .} . void main() {C3 a.numevar1)..int x1.1.12..afis("CONSTRUCTOR_5").strcpy(numevar. A1(char*..int.. m[0]=&r1. return 0.... explicitarea unui constructor şi explicitarea funcţiei operator). a. void C3::afis(char *str) {cout<<”C3_var:”<<numevar<<” tip:”<<str<<endl. }.TEST #6 Se dau următoarele clase: #include #include #include #include <conio.int y1.. Clasa conţine o variabilă ce }.3.44)...ya=0..45).000.. a>xa=(int)&m[0]. protected: int h. B2 r2("var-r2"... m[2]=&r3.} iar class C3:public A1 in loc de class C3:private A1 şi class B2:public A1 în loc de class B2:protected A1 class C3: private A1 { public:int xc. void main() {A1 d1[2]. yb=0...yb=0.7.afis("CONSTRUCTOR_3").int x1. ~B2() {afis("DESTRUCTOR").ya=y1...43..h> <string.} . A1::A1(char *numevar1) {xa=0.} 2. B2(char *numevar1):A1(numevar1) {xb=0.w2("d1". int x1) {xa=x1..xa=7. void tipar().. 2. a. void main() {B2 d1[2].strcpy(numevar. } A1::A1(char *numevar1.numevar1)..ya.. A1(char*.char numevar[20].. } m[0]->tipar().} 4.yc=0. d1[1].yc=0. void main() {A1 m[2].. ~A1() {afis("DESTRUCTOR").h=5. afis("CONSTRUCTOR_1").} .x1. C3 m1("m1"). void main() C3():A1(){xc=0. } getch(). void main() {B2 d1[2]. C3 a. int m[1]->tipar().} void C3::tipar() {cout<<”xc=”<<setw(7)<<setfill('#')<<hex<<xc<<en dl.h> <iostream.48.*g1.int)..g=3. C3(char *numevar1. 2. memorează numărul se minute raportat la 31. ora 24:00:00.g=1.15.41). C3(char *numevar1):A1(numevar1) C3 r3("var-r3".g=9. date calendaristice.} . d1[1].strcpy(numevar. 2.afis("CONSTRUCTOR_0”).int x1.} .h> <iomanip.numevar1).49. void main() {C3 a. 2.ya=0. delete g1. void tipar().

r1("var-r1". A1() {xa=0.m[1]=&r2. void tipar()... r1=new A1("r1".xa=7..g=9..2..... protected: int h.} void A1::tipar() {cout<<”xa=”<<setw(7)<<setfill('*')<<hex<<xa<<en dl. void main() {B2 d1[2].} void C3::tipar() {cout<<”xc=”<<setw(7)<<setfill('*')<<hex<<xc<<en dl.g=3.ya=0.........1. A1(char *numevar1..h=7........... void main() {C3 a.... .ya=y1.yc=0...3). a... C3 m1("m1").} virtual void afis(char *str). class A1 {int g... A1(numevar1.int x1. void main() {A1 m[2]. virtual void tipar().....} 2..15).yb=0..strcpy(numevar....yc... explicitarea destructorului şi explicitarea funcţiei operator)..2.... } m[2]->tipar()...6..13...} A1(char *numevar1..h> <iomanip.} 2... getch().... m[1]->tipar().strcpy(numevar. {A1 w2("d1". C3 a. void main() {C3 a... void main() {A1 *m[2].9..yc=t1.. 2.x1) { xb=m1... int x1) {xa=x1.ya..} ~A1() {afis("DESTRUCTOR")... a... void main() {A1 m[2]. a....h> <iostream.. }... 4..... 2.. afis("CONSTRUCTOR_1")...... C3(char *numevar1. R: 2..afis("CON 2.. 2....int s1...} void B2::tipar() {cout<<setw(7)<<setfill('*')<<”xb=”<<hex<<xb<<en dl.8.h=5. d1[0]. m[2]=&r1..... static: int 2.. int y1) {xa=x1.yb.} getch(). explicitarea unui constructor.strcpy(numevar.5.} void afis(char *str)..} }.xa=1..ya=0.. a=m[0]... 3. Ce se afişează în urma execuţiei ? int main() { A1 *r1.} .. d1[1]. m[0]=@a.Este posibilă execuţia următoarelor instrucţiuni? Explicaţi de ce! .} iar class C3:public A1 in loc de class C3:protected A1 C3(char *numevar1):A1(numevar1) {xc=0. void main() {B2 d1[2]. public:int xa............ void tipar().} class B2: public A1 { public:int xb... int C3 r3("var-r3".afis(" 2.h> } delete r1.. B2(char *numevar1):A1(numevar1) {xb=0........7.} ONSTRUCTOR_2")... C3():A1(){xc=0.d1[2].} B2(char *numevar1. ~B2() {afis("DESTRUCTOR").} } . Ce se afişează în urma execuţiei ? void B2::afis(char *str) {cout<<”B2_var:”<<numevar<<” tip:”<<str<<endl..5...char numevar[20].3.. B2 g2("g2").int x1. . afis("CONSTRUCTOR_1")...} 2.4. d1[1]..4.. } de caractere (această clasă va conţine un pointer la un şir de caractere).11.6.afis("CONSTR UCTOR_0”).. ..10..} s. CONSTRUCTOR_3")...strcpy(numevar...... void main() } {A1 *m[3].g=1...afis("C 2. Se dă o clasă ce gestionează elementele unui şir void C3::afis(char *str) {cout<<”C3_var:”<<numevar<<” tip:”<<str<<e.....int y1. {xc=s1.ya=0....afis("CONSTRUCTOR_0”)....7)..h> <string.} 1.} class C3: protected A1 { public:int xc............12)..numevar1). void main() {B2 d1[2].. yb=0....x1...numevar1).} ..numevar1). void main() {A1 d1[2]..} A1(char *numevar1) {xa=0...... d1[1]..61)..} ...yc=0.afis("CONSTRUCTOR_3").. B2 r2("var-r2".int m1): A1(numevar1...afis("CONSTRUCTOR_5").TEST #7 Se dau următoarele clase: #include #include #include #include <conio... a>xa=(int)&m[0].. }... Să se supraîncarce un operator care să permită adăugarea unui caracter la sfârsitul şirului (se va scrie declaraţia clasei....y1) m[0]->tipar()..} STRUCTOR_1"). ~C3() {afis("DESTRUCTOR").... return 0.”N/A”).. C3 *a. void A1::afis(char *str) {cout<<”A1_var:”<<numevar<<” tip:”<<str<<endl. t1): m[0]=&r3.int x1... void main() {C3 a..} void afis(char *str).. C3 *a.....

.x1) { xb=m1. int).52..} iar class C3:public A1 in loc de class C3:private A1 şi class B2:public A1 în loc de class B2:protected A1 void main() {A1 *m[3]....} ..afis("CONSTRUCTOR_3"). 2. afis("CONSTRUCTOR_3"). void C3::afis(char *str) {cout<<”C3_var:”<<numevar<<” tip:”<<str<<endl.... Să se supraîncarce un operator care să permită adunare cu un anumit număr de zile (se va scrie declaraţia clasei... } ~C3() {afis("DESTRUCTOR")..4.1.numevar1). r1=new A1("r1".ya=0.g=3. m[2]=&r3.} virtual void afis(char *str).} d1[2]..53).. 2..char numevar[20].. void main() {C3 a. B2 r2("var-r2".xa=1. B2(char *numevar1):A1(numevar1) {xb=0..r1("var-r1". m[2]->tipar()..yc.strcpy(numevar. } C3(char *numevar1.int x1. getch(). void main() {A1 m[2]. void void void void void main() main() main() main() main() {A1 {B2 {B2 {B2 {C3 d1[2].8. C3 *a..} void afis(char *str).. afis("CONSTRUCTOR_0”).g=9.} class C3: private A1 { public:int xc. afis("CONSTRUCTOR_1")..ya.57).11. m[1]->tipar(). int t1): A1(numevar1.. Ce se afişează în urma execuţiei ? int main() {A1 d1[2]. Ce se afişează în urma execuţiei ? void A1::tipar() {cout<<”xa=”<<setw(7)<<setfill('^')<<hex<<xa<<en dl....} 1. 2. a..ya=0. void main() {C3 a..19).... afis("CONSTRUCTOR_1"). } void A1::afis(char *str) {cout<<”A1_var:”<<numevar<<” tip:”<<str<<endl.h> <iomanip. delete g1.h=7.5.} .51). .. }..strcpy(numevar.g=1. d1[0].. A1::A1(char *numevar1) {xa=0.54.. getch().h> B2 *g1. static int s.. 4.xa=7. m[0]->tipar().61).} void B2::tipar() {cout<<setw(7)<<setfill('~')<<”xb=”<<hex<<xb<<en dl..} B2(char *numevar1. C3 *a. int x1) {xa=x1. a>xa=(int)&m[0]..} void C3::tipar() {cout<<”xc=”<<setw(7)<<setfill('#')<<hex<<xc<<en dl. public:int xa. A1(char*.yc=t1.x1. d1[1].2..”N/A”)..numevar1). C3 a. 2.} } void B2::afis(char *str) {cout<<”B2_var:”<<numevar<<” tip:”<<str<<endl.... int y1) {xa=x1...m[1]=&r2.. A1(char*.y1) {xc=s1.21.1899..int m1): A1(numevar1.. void main() {A1 *m[2].. a. } delete r1.. yb=0.10...... 2. ora 24:00:00.. A1() {xa=0. 2..numevar1).strcpy(numevar.yb.h> <iostream. } {C3 m1("m1"). 2.} class B2: protected A1 { public:int xb. {A1 w1("d1")..} a. ~B2() {afis("DESTRUCTOR"). return 0.strcpy(numevar. } A1::A1(char *numevar1....h> <string.. d1[1]. C3():A1(){xc=0. }. afis("CONSTRUCTOR_1").000..3.int s1. g1=new B2("g1". virtual void tipar().} .afis("CONSTRUCTOR_5").} 2. 2. 2.int.. } A1::A1(char *numevar1. m[0]=&r1.. explicitarea unui constructor şi explicitarea funcţiei operator).....} C3(char *numevar1):A1(numevar1) {xc=0.} d1[2].. d1[1].h=5.int y1. void main() {A1 m[2]. Se dă o clasă pentru gestiunea operaţiilor cu date calendaristice. } A1(char*).. ~A1() {afis("DESTRUCTOR")..*r1...int x1.12.} d1[2]..ya=y1. void tipar(). protected: int h.} .9.. Clasa conţine o variabilă ce memorează numărul se minute raportat la 31....7.. ...ya=0.TEST #8 Se dau următoarele clase: #include #include #include #include <conio.int x1.55.. C3 r3("var-r3".yb=0.. void tipar().} 3.afis("CONSTRUCTOR_0”).. }. a=m[0].Este posibilă execuţia următoarelor instrucţiuni? Explicaţi de ce! 2.yc=0.6.int). } class A1 {int g. a.yc=0.} void afis(char *str). afis("CONSTRUCTOR_2").56. m[0]=@a.

12.strcpy(numevar. int). 4.afis("CONSTRUCTOR_3").y1) 31. . static int s. B2(char *numevar1):A1(numevar1) {xb=0.h> <iomanip.xa=7. return 0.numevar1).int s1. a. C3 *a. }.m[1]=&r2. void main() {B2 d1[2].37).yb=0. } class A1 {int g. A1::A1(char *numevar1) {xa=0. a=m[0].36.} 1.TEST #9 Se dau următoarele clase: #include #include #include #include <conio.char numevar[20]. d1[0].9.int m1): A1(numevar1.} 2.10. d1[1]. void main() {A1 m[2].int.1899. .yc=t1. m[2]=&r1. explicitarea unui }. void tipar().g=1. 2.000.afis("CONSTRUCTOR_0”). void main() {C3 a. {xc=s1.} 2.int x1.numevar1). } void A1::afis(char *str) {cout<<”A1_var:”<<numevar<<” tip:”<<str<<endl.strcpy(numevar.32.} C3(char *numevar1):A1(numevar1) {xc=0.strcpy(numevar.} 2.int y1.6.} iar class C3:public A1 in loc de class C3:private A1 şi class B2:public A1 în loc de class B2:protected A1 void main() {A1 *m[3]. afis("CONSTRUCTOR_2"). } A1(char*).g=3.1. } getch().5. d1[1]. void main() {C3 a.} 2.21.} virtual void afis(char *str). A1() {xa=0.} 2. afis("CONSTRUCTOR_1"). ~B2() {afis("DESTRUCTOR"). yb=0. C3():A1(){xc=0.int x1. scrie declaraţia clasei.4). void main() {B2 d1[2]. void main() {B2 d1[2].yc=0. getch().yb. a>xa=(int)&m[0].int x1. C3 a. int y1) {xa=x1.1. m[0]=&r3. 3.afis("CONSTRUCTOR_5").} 2.ya. g1=new B2("g1". A1(char*.h=5.h> <iostream. d1[1].35.34. } delete g1.} void C3::tipar() {cout<<”xc=”<<setw(7)<<setfill('#')<<hex<<xc<<en dl. B2 r2("var-r2".} } void B2::afis(char *str) {cout<<”B2_var:”<<numevar<<” tip:”<<str<<endl. void main() {A1 *m[2].xa=1. void main() {A1 m[2]. B2 *g1.8.} void afis(char *str). Ce se afişează în urma execuţiei ? int main() { C3 m1("m1").4).2. A1(char*. int t1): memorează numărul se minute raportat la A1(numevar1.} 2. a. C3 r3("var-r3". } Să se supraîncarce un operator care să permită ~C3() {afis("DESTRUCTOR").} 2. ~A1() {afis("DESTRUCTOR").Este posibilă execuţia următoarelor instrucţiuni? Explicaţi de ce! 22.yc.7. m[0]=@a. public:int xa. Se dă o clasă pentru gestiunea operaţiilor cu } date calendaristice. Ce se afişează în urma execuţiei ? void A1::tipar() {cout<<”xa=”<<setw(7)<<setfill('^')<<hex<<xa<<en dl.} adunare cu un anumit număr de secunde (se va void afis(char *str). afis("CONSTRUCTOR_0”).int).g2("g2". } A1::A1(char *numevar1. }. protected: int h.33).numevar1).x1) { xb=m1. C3 *a. void main() {C3 a. a.4. m[0]->tipar().17).5. afis("CONSTRUCTOR_1"). m[1]->tipar().h> {cout<<”C3_var:”<<numevar<<” tip:”<<str<<endl.} class B2: protected A1 { public:int xb. {A1 w2("w2".h=7. void C3::afis(char *str) constructor şi explicitarea funcţiei operator). virtual void tipar(). void main() {A1 d1[2].31).} 2.h> <string.3. } A1::A1(char *numevar1.yc=0..ya=y1. ora 24:00:00. Clasa conţine o variabilă ce C3(char *numevar1. int x1) {xa=x1.ya=0.”N/A”).g=9.strcpy(numevar.} class C3: private A1 { public:int xc.ya=0..} B2(char *numevar1.} . {A1 d1[2]. afis("CONSTRUCTOR_1").r1("var-r1". afis("CONSTRUCTOR_3").} void B2::tipar() {cout<<setw(7)<<setfill('~')<<”xb=”<<hex<<xb<<en dl. void tipar().ya=0.x1. m[2]->tipar().

y11) {numevar=new char[100].} construcorul implicit? class B2: public A1 2.y1.21. } C3 m2("m2". posibil accesul lui g1->t1? Explicaţi! public: Dar al lui m1->t1 ? Explicaţi! B2(char *numevar1):A1(numevar1) {numevar=new char[100].} void afis(char *str). B2(char *numevar1.s1=-1.x11.str. 4.numevar1).//4.str. {numevar=new char[100].t1=-1. char* argv[]) x1=0. 4.int y11.afis("CONSTRUCTOR2 delete r1.x2. g1=new B2("g1".numevar1).numevar:%s x2=%d y2=%d s2=%d d[2].17.} return 0. Afişaţi acest număr în } cadrul constructorilor şi destructorilor.s1.t1). A1(char *numevar1) B2 *g1.? public: C3(char *numevar1):A1(numevar1) Explicaţi!.x3.int x11. afis(“d[i]”) . public: int t1.1. A1"). s3=s33.2 d[0].54).4.Ce va afişa funcţia afis(char *str) dacă nu void calc(). s2=0.3 {printf("\n %s -.int x11.3 t2=%d". { strcpy(numevar.2.} class A1 {int x1.54).3.h> C3(char *numevar1. d[2]=m2. Ce se afişează în urma execuţiei ? A1() {numevar=new char[100].s3=0. .Se dă: A1(numevar1.s1=-1.afis("CONSTRUCTOR2 B2").17. Ce va afişa funcţia afis(char *str) dacă nu este apelată prima în cadrul unui destructor? void A1::afis(char *str) {printf("\n %s -.5.s2.afis("d[1]"). Adăugaţi câte un contor pentru numărul de strcpy(numevar. ~B2() {afis("DESTRUCTOR B2"). 1.5.numevar1).x1.21. A1 w2("d1". ~A1() {afis("DESTRUCTOR A1").1 sau 2 ? Explicaţi! afis("CONSTRUCTOR1 C3").afis("CONSTRUCTOR_0 {C3 *m2. {numevar=new char[100]. C3 m1("m1").int s22): 4. return 0. A1(char *numevar1.delete[] numevar.32.y1. void afis(char *str).t1=-1.numevar. virtual void afis(char *str). 3.numevar. delete g1.t3=0.4). pentru fiecare clasă în parte x2=0.int x11.t1=-3. y2=0.// 4. Este posiblil asignarea „d[1]=g2”.y11) int main(int argc. int x3.numevar:%s x1=%d y1=%d s1=%d t1= 2. d[1]=g2. se afişează în urma apelului metodei x3=0.1.//4.g2("g2"). Este posiblil asignarea „d[2]=m2”.numevar1). } ~C3() {afis("DESTRUCTOR C3").Pentru variabilele declarate la pct.strcpy(numevar.delete[] numevar. A1"). metodele modificate). protected: int s1.2.w1("d1").w2("d1". }. //4.3 void B2::afis(char *str) d[1]. derivate? protected: 2.x1.y1. } . Este int s2.numevar1). În cazul în care este posibilă asignarea ce strcpy(numevar. delete m2.y3.s1. x1=0. char *numevar.32.101.numevar:%s x3=%d y3=%d s3=%d t3=%d". din clasa de bază şi cea declarată în clasele int x2. obiecte instanţiate. int y11) r1=new A1("r1".19).h> #include <stdio.afis("d[2]").y3.y2. 2.int s33): A1(numevar1.//4. A1 *r1.4 Ce legătură există între variabila numevar { char *numevar.5.19).t2.t1.1. {numevar=new char[100].} getch(). s2=s22.61). } private: 2.1 }.y1=0. (adăugaţi direct pe codul scris şi rescrieţi numai afis("CONSTRUCTOR1 B2").101.str.h> #include <string.int y11.} m2=new C3("m2".3 De ce nu a putut fi afişat numevar şi pentru %d".s1=-3. este apelată ultima în cadrul unui constructor? }. s1=0. s1=-2.y3=0.s3.d[3].x11. void C3::afis(char *str) {printf("\n %s -.t1=0. i=0.numevar1).4).numevar.t2=-2.t3). class C3: protected A1 } { char *numevar.y1=0.t2). B2 g2("g2". int main(int argc.} {A1 d1[2]. t2=0.delete[] numevar.t3.afis("CONSTRUCTOR1 A1").} d[0]=w2. y1=y11.? protected: Explicaţi! int s3. char* argv[]) { numevar=new char[100].y2. strcpy(numevar.11.TEST #10 Se dau următoarele clase: #include <conio.afis("d[0]").} getch().afis("CONSTRUCTOR2 C3")."N/A"). strcpy(numevar. } x1=x11. strcpy(numevar.

org/Main/ReadMore Dan Somnea. Editura Tehnica 1993.org/papers/C++-Book/ http://codelite.Doru Turturea. Initiere in C++ programarea orientata pe obiecte .unixinside.BIBLIOGRAFIE http://www.