Admin
Administrator
Inregistrat: acum 14 ani
Postari: 315
|
|
C++ este un limbaj de programare orientata pe obiecte. Acest limbaj constituie o versiune imbogatita a limbajului de programare C (o extensie sau un superset al lui C). Pana in 1983 el se mai numea C cu clase.
Sa precizam cateva din elementele specifice lui C++. Ele constau in extensii ale lui C cu privire la:
a) limbaj: 1. pentru o parcurgere facila a codului sursa, se foloseste un nou mod de prezentare a comentariilor; 2. se utilizeaza tipurile referinta, care simplifica, din punct de vedere sintactic, transmiterea parametrilor prin referinta; 3. se foloseste supraincarcarea operatorilor, cu scopul de a permite, in C++, sa actioneze asupra tipurilor abstracte de date definite de utilizator; 4. se foloseste supraincarcarea functiilor, care permite utilizarea mai multor functii cu acelasi identificator, dar cu actiuni diferite; 5. se utilizeaza functiile cu parametri impliciti.
b) o tratare la nivel superior a tipurilor de date definite de utilizator ce consta in: 1. folosirea prototipurilor functiilor, care permit o buna verificare a tipurilor parametrilor, la apelul lor; 2. folosirea operatorilor de alocare dinamica a memoriei, care dau o precizie mai mare, in aceasta operatie; 3. verificarea transferului de parametri, printr-un control al tipurilor, la editarea de legaturi; 4. o noua interfata intrare/iesire (I/O), care da o mai mare flexibilitate, a operatiilor de citire / scriere; 5. existenta unor rutine care permit conversia tipurilor definite de utilizator.
c) programarea orientata pe obiect (OOP) reflectata prin: 1. gruparea de date si operatii intr-un acelasi tip de date numit clasa; 2. un acces selectiv la elementele interne ale unei clase; 3. reutilizarea sau mostenirea unor clase prin clase derivate; 4. utilizarea functiilor virtuale, care dau un mijloc mai puternic de apelare al functiilor, in timpul executiei programului si nu in timpul compilarii lui; 5. utilizarea functiilor friend, care permit accesul din exteriorul unei clase, la elemente protejate din acea clasa; 6. utilizarea unor functii speciale intr-o clasa numite constructori respectiv destructori, necesare pentru a initializa, respectiv a distruge, obiecte ale acelei clase.
Necesitatea introducerii lui C++ se datoreaza si cresterii complexitatii programelor (trecand de 25000 de linii de cod, un control in C devine anevoios). De la aparitie, C++ a trecut printr-o serie de revizuiri (1985, 1989, iar in 1994 se obtine standardul ANSI C++).
C++ fiind un superset al lui C, permite compilarea unor programe ANSI C cu un compilator C++, luand in considerare unele aspecte specifice.
1) Evitarea utilizarii unor identificatori in ANSI C care sa fie identici cu unele cuvinte cheie din C++. Intr-un program C se pot utiliza drept identificatori de variabile cuvinte cheie ca: this, new, public, dar nu in situatia in care compilarea surselor se face cu un compilator C++. 2) Domeniul de vizibilitate al identificatorului unui tip enumerat declarat in cadrul unei structuri in C coincide cu cel al identificatorului structurii respective. In C++ el este vizibil doar in cadrul acestei structuri. De aceea este bine ca atribuirile sa fie insotite de conversii de tip corespunzatoare. Exemplu: struct alfa { enum cod {cif,lit,semn}; };
Intr-un program C, instructiunea: cod c1=semn; este corecta. In C++ ea trebuie rescrisa sub forma: alfa::cod c1=alfa::semn; (asupra operatorului "::" vom reveni).
3) In C este permisa conversia implicita a pointerilor generici (void) in alte tipuri de pointeri, pe cand in C++ nu este permisa o astfel de conversie. In C++ toate valorile zero sunt codificate prin 0, iar in ANSI C, unde sunt referiti pointeri, este adesea utilizata constanta NULL. Desi diferenta este pur stilistica, ea este adoptata permanent.
4) In ANSI C se presupune ca orice functie nedeclarata are un prototip de forma int id_functie(
.); In C++, nu se poate apela o functie nedeclarata, si se va semnala eroare la compilare.
5) Declaratia unei functii in care lista parametrilor lipseste, este diferit interpretata in C++ fata de ANSI C. De exemplu, void func ( ); in C++ este interpretata sub forma void func(void); cu o lista vida de parametri. In ANSI C este interpretata sub forma void func(
); ceea ce nu indica lipsa definitiva a parametrilor.
6) Exista diferente intre lungimile unor tipuri de date. Astfel, in ANSI C, sizeof('c'); este acelasi cu sizeof(int) (=2 oct); oricare ar fi caracterul ASCII, 'c'. Compilatorul C interpreteaza constanta caracter 'c' ca o constanta intreaga. Prin urmare, in ANSI C, sunt sinonime apeluri de functii de forma: putchar(10); putchar('\ n'); In C++, sizeof ('c'); este sinonim cu sizeof (char)(=1 oct);
Functiile, in C++, difera intre ele prin argumentele lor. In cazul de fata un apel de functie solicita un int iar celalalt apel un char. 7) O linie de comentariu in C++ incepe cu "//".
Exemplu: // acesta este un comentariu Ramane valabila si constructia din C /*comentariu */
Un programator trebuie sa tina cont de faptul, ca pentru a fi portabil, un program C++ trebuie sa aiba acelasi efect, indiferent de masina fizica sau mediul de lucru care au fost folosite. Un program C++ portabil nu depinde de factori ca: a) ordinea de evaluare a parametrilor functiilor; b) ordinea de evaluare a operanzilor operatorilor binari; c) numarul de pozitii binare shift-abile la stanga sau la dreapta; d) modul in care se efectueaza operatia de complementare ~ in functie de masina utilizata; e) precizia de reprezentare si ordinul de marime al variabilelor de tip float si double; f) ordinea bitilor intr-un octet; g) restrictiile cu privire la alinierea datelor in memorie; h) setul de caractere utilizat (ASCII,EBCIDIC,
); i) valoarea initiala a variabilelor automatice ramase neinitializate; j) ordinea in care se construiesc obiectele globale (definite in exteriorul oricarei functii) etc.
Functiile normale C, adica cele care sunt compilate si depozitate intr-o run-time library, se pot utiliza in programe C++ cu conditia ca ele sa fie totusi declarate ca functii C.
Majoritatea diferentelor de stil, intre programele redactate in C si cele in C++, se regasesc in avantajul pe care il are C++ cu privire la capacitatea sa de orientare pe obiecte. De aceea este bine a gandi si programa in C++ fara a apela la C.
Trebuie sa avem in vedere caracteristicile specifice programarii in C++. Se stie ca un stream (flux) reprezinta o colectie de octeti care serveste ca model abstract pentru dispozitive de intrare/iesire ca: fisier pe disc, tastatura, ecran, buffer pentru memorie. Borland C++ include biblioteca iostream care trateaza operatiile de intrare/iesire prin intermediul unei clase de obiecte. Reducerea duratei, in trecerea de la stdio (C) la iostream (C++), se bazeaza tocmai pe faptul ca biblioteca iostream contine obiecte predefinite de tip stream (cin, cout, cerr) care au un rol similar din punct de vedere functional cu stdin, stdout, stderr din C.
Operatiile de intrare / iesire la nivel de consola, specifice lui C++, se bazeaza pe aceste fluxuri predefinite: a. cin un flux de intrare conectat la intrarea standard - tastatura (analog cu stdin din C); b.cout - un flux de iesire conectat la iesirea standard - monitorul (analog cu stdout din C); c.cerr- un flux de iesire care furnizeaza o iesire fara a folosi buffer la dispozitivul standard de eroare (analog cu stderr din C); d. clog- un flux care foloseste buffere la fel ca cin si cout (analog cu cerr).
Cand isi incepe executia un program in C++, se deschid automat aceste patru stream-uri incorporate. Implicit, stream-urile standard sunt folosite pentru a comunica cu consola. In mediile care admit redirectionarea I/O (DOS, Unix, OS/2,Windows),stream-urile standard pot fi redirectionate spre alte echipamente sau fisiere. Standardul ANSI C++ mai defineste urmatoarele patru stream-uri:win, wout,werr si wlog. Ele constituie versiuni ale stream-urilor standard pentru caractere mari (wide caracters). Acestea sunt de tipul wchar_t si, in general, au marimea de 16 biti. Sunt folosite pentru seturile largite de caractere necesare anumitor limbi. In loc de a defini functii membre ale unei clase, care sa realizeze operatiile de intrare/iesire, biblioteca iostream are in vedere supraincarcarea operatoriilor <<si>>. Acesti operatori conlucreaza cu fluxurile cin si cout.
ecran buffer operatorul << reprezentare interna (binara) cout este conectat la ecran; bufferul este asociat fluxului de iesire cout; operatorul <<converteste>> reprezentare interna (binara)
cin este conectat la tastatura; bufferul este asociat fluxului de intrare cin; operatorul >> converteste caracterele in reprezentarea binara interna.
Biblioteca C++ iostream constituie o implementare orientata pe obiecte a unui flux de octeti de la o sursa la o destinatie. In aceasta biblioteca se afla fluxuri de intrare (clasa istream similara, din punct de vedere functional, cu scanf si fscanf (din ANSI C)), fluxuri de iesire (clasa ostream similara, din punct de vedere functional, cu printf si fprintf (din ANSI C)) si fluxuri care pot trata atat operatii de intrare cat si de iesire (clasa iostream).
Stream-urile de intrare / iesire supraincarca operatorii binari de shiftare >> (EXTRACTIE, adica preia de la
), <<INSERTIE>> este util pentru intrare (cin), iar <<pentru>>car; cout<<car>>v1>>v2>
.>>vn; cout<<v1<<v2<<..<<vn;
Nu se accepta decat inlanturi cu operatori de acelasi fel.
Exemplu: #include<iostream> void main (void){ int x,y; float z; cout<<"Introduceti un intreg /un real\n"; cin>>x>>z; y=x+2; cout<<"x+z="<<(x+z)<<"x&y="<<(x&y)<<"\n"; } Parantezele sunt necesare avand in vedere precedenta operatorilor utilizati.
Tipurile datelor citite de la cin pot fi tipuri aritmetice si siruri de caractere. Tipurile datelor transferate catre cout sunt aceleasi ca la citire. In plus, ele pot fi si pointeri de un tip oarecare, cu exceptia tipului char.
Extragerea unei valori numerice inseamna: - ignorarea tuturor caracterelor spatiu, adica acele caractere pentru care functia de biblioteca isspace(), returneaza o valoare nenula (blancul, '\ t', '\ v', '\ n' etc.); - un text, daca primul caracter diferit de caracter_spatiu este o cifra, un semn sau punctul zecimal (la float); - extragerea tuturor caracterelor consecutive pana la intalnirea unui caracter invalid pentru tipul de data respectiv; - efectuarea, la final, a conversiei string-ului obtinut la tipul de data respectiv.
Sa analizam urmatorul exemplu: #include <iostream> main ( ) { int k=5; cout<<"IESIREA\n"; //comentariu in C++ cout<<"Introduceti o valoare:"; cin>>k; cout<<k<<"la cub este:"<<k*k*k<<"\ n"; return 0; } a) Se observa ca este inclus fisierul antet iostream.h, util in admiterea operatiilor de intrare / iesire in C++. Acest fisier contine definitiile claselor care implementeaza obiectele fluxuri si permit folosirea bufferelor. El joaca un rol similar lui stdio.h din C. b) Se va retine faptul ca lista de parametri din main( ) este vida. In C++ aceasta inseamna ca functia nu are parametri. In acest caz, in C++, utilizarea lui void devine superflua.
c) In urmatoarele linii apare supraincarcat operatorul <<respectiv>>, in sensul precizat mai sus, specific lui C++.
d) Se poate utiliza si printf( ) din C, dar cu includerea lui stdio.h.
e) Operatorii de deplasare, atunci cand nu sunt folositi in operatiile de intrare / iesire, vor indica operatiile de deplasare stanga / dreapta corespunzatoare. f) In linia de cod cin>>k; nu este necesar & in fata lui k (detalii la stream-urile definite in C++).
g) Pentru k=5, prin penultima linie, se va tipari valoarea 125.
h) Returnarea valorii 0 unitatii apelante (de obicei sistemul de operare), indica o terminare normala a programului. Altfel, in caz de eroare, se va returna o valoare diferita de 0.
i) Exista doua posibilitati, in C++, in ceea ce priveste tipul returnat de functia main ( ): - nu declaram nimic, ceea ce inseamna ca tipul returnat este void; - returneaza o valoare intreaga. Nu este obligatoriu ca o astfel de functie sa returneze o valoare.
j) Un astfel de program nu apeleaza la constructii din C, ci utilizeaza numai constructii specifice lui C++.
Exista o serie de functii care pot fi utilizate in combinatie cu operatorii de intrare / iesire. Iostream poseda, dupa cum am mai mentionat, o serie de rutine pentru acces la nivel de caracter. Majoritatea acestora apartin clasei istream si sunt asociate operatiilor de intrare (intrari neformatate). Exista o metoda, mai des intalnita, folosita pentru operatia de iesire, put( ), care face parte din clasa ostream. Intrarea unui singur caracter se poate realiza cu ajutorul functiei get( ) a clasei istream. int get(void); Se extrage urmatorul caracter de la intrare si-l returneaza. Daca este detectat sfarsitul intrarii, se returneaza EOF. int peek(void); Se returneaza urmatorul caracter de la intrare, fara a-l extrage. Daca este detectat sfarsitul intrarii, se returneaza EOF. istream &putback(char c); Se intoarce caracterul c la intrare si returneaza o referinta.
istream &get(signed char &c); istream &get(unsigned char &c); Se extrage caracterul urmator de la intrare si returneaza intrarea ca referinta. Se poate spune ca functia get( ) extrage un caracter din stream-ul curent si-l pastreaza in zona de memorie referita de parametrul formal c. Aceasta functie nu trece peste caracterele albe. Ea extrage din stream-ul curent caracterul, indiferent daca acesta este sau nu un caracter alb. istream &get(signed char *s,int n, char t='\n'); istream &get(unsigned char *s,int n, char t='\n'); Se extrag cel mult n caractere (un sir, inclusiv \0) din stream-ul curent de la intrare si le depun in sirul s. Daca se detecteaza terminatorul de sir t, extragerea se opreste fara a se realiza extragerea si depunerea terminatorului in sirul s. istream &getline(signed char *s,int n, char t='\n'); istream &getline(unsigned char *s,int n, char t='\n'); Aceeasi actiune ca si get( ), cu deosebirea ca terminatorul de sir este extras de la intrare, dar nu este depus in sir. istream &ignore(int n, int t=EOF); Extrage si ignora cel mult n caractere de la intrare, inclusiv terminatorul t. int gcount(void); Returneaza numarul de caractere extrase la ultima operatie de extragere. Extragerea binara a datelor din stream-ul curent se realizeaza folosind functia read( ). istream &read(unsigned char*s, int n) ; istream &read(signed char*s, int n) ; Se extrag n octeti din stream-ul curent si ii transfera in zona de memorie referita de s. ostream &put(char c); Se introduce caracterul c la iesirea ostream si returneaza o referinta. Exemplu: // apeluri in C //apeluri in C++ c= fgets(stdin); c=cin.get( ); fgets(buff,80,stdin); cin.getline(buff,80); ungetc(c,stdin); cin.putback(c ); fputc(c,stdout); cout.put(c ); Analizati astfel de apeluri si precizati efectul lor.
Exista posibilitatea concatenarii unor operatii de intrare/iesire. Sa presupunem ca dorim a afisa caracterele:'B', 'C', 'D'. O varianta consta in a folosi in mod individual metoda put( ): cout.put('B'); cout.put('C'); cout.put('D'); O alta varianta, mai compacta, ar fi urmatoarea: cout.put('B').put('C').put('D'); sau inca ((cout.put('B')).put('C')).put('D') (se are in vedere asociativitatea la stanga a operatorului ".". Sa se faca o analogie cu printf( ).
Atributele de orientare pe obiecte pot fi potential aplicate tuturor sarcinilor de programare. C++ se poate utiliza si pentru obiecte ca: editoare, baze de date, fisiere de personal, programe de comunicare. Cu ajutorul lui C++ s-au creat multe sisteme de inalta performanta.
Programarea orientata pe obiect (OOP) constituie o noua cale de abordare a programarii. Se poate spune, ca datorita cresterii continue a complexitatii programelor, OOP vine sa salveze programarea structurata care devine aproape ineficienta in astfel de conditii. OOP preia cele mai reusite aspecte ale programarii structurate si le combina cu mai multe concepte noi, puternice. Ideea OOP conduce la divizarea unei probleme in subgrupe de sectiuni inrudite care tin cont de codul si de datele corespunzatoare din fiecare grup, organizandu-le intr-o structura ierarhica.
Limbajele de programare orientata pe obiect poseda trei concepte fundamentale: incapsulare, mostenire, polimorfism.
Incapsularea permite crearea unor obiecte (entitati logice care cuprind atat date cat si un cod ce prelucreaza aceste date). Ea consta intr-un mecanism care leaga codul cu datele si le pastreaza in siguranta. Adica, un obiect poseda un anumit nivel de protectie, in sensul ca nu se pot produce modificari accidentale sau o utilizare incorecta a unor parti proprii ale acelui obiect de catre anumite sectiuni ale programului cu care nu are nici o legatura. Un obiect se va identifica printr-o variabila de un tip definit de utilizator. Cand in OOP se defineste un obiect, in mod implicit, se creeaza un nou tip de date. Un obiect real este caracterizat prin structura si functionalitate. El poate fi supus unei evolutii pastrandu-si identitatea, dar modificandu-si structura si / sau aspectele sale functionale. Ca o concluzie, obiectul constituie conceptul de baza in OOP si cuprinde o structura de date si metode de operare.
Tipurile abstracte de date se vor defini cu ajutorul conceptului de clasa. Clasele se afla la baza programarii orientata pe obiect. Clasa este utila in definirea naturii unui obiect si constituie unitatea de baza pentru incapsulare.
Mostenirea consta intr-un proces prin care un obiect poate prelua prototipul unui alt obiect. Ea permite construirea unei ierarhii de clase, prin trecerea de la cele generale la cele particulare (clasa de baza - clasa derivata). Fiecare obiect trebuie definit prin punerea in evidenta a tuturor caracteristicilor sale. Mostenirea insa, ofera posibilitatea definirii doar acele caracteristici ale obiectului, care il identifica in mod unic in clasa sa.
Ierarhia se produce intre diverse forme de existenta a materiei si diferite fenomene. In varful ierarhiei se va afla acel obiect care va avea trasaturi comune cu toate celelalte componente din ierarhie. Ierarhia se poate prezenta sub o forma arborescenta. Odata stabilita, intre mai multe concepte, ea nu este neaparat unica. In OOP se permite definirea de ierarhii intre tipuri abstracte de date pe baza conceptului de mostenire.
In C++, ierarhia intre tipuri abstracte de date se exprima prin ierarhia de clase care implementeaza acele tipuri abstracte de date. Aceasta ierarhie se stabileste pe baza conceptelor de clasa de baza si clasa derivata (aceste concepte vor fi analizate pe parcurs). paralelogram romb patrat dreptunghi
Polimorfismul este caracteristic programarii orientata pe obiect. El ar putea fi interpretat ca o interfata /metode multiple. Acesta ofera posibilitatea ca o interfata sa fie folosita cu o clasa generala de actiuni. Compilatorul C++ permite ca polimorfismul sa fie admis atat in timpul rularii cat si al compilarii. Intr-o ierarhie de clase, care are la baza conceptul de mostenire, polimorfismul este pus in evidenta prin functii membre (metode prezente intr-o clasa) care pot avea forme diferite de la un nivel la altul.
Tehnica programarii orientata pe obiect difera de cea a programarii structurate, prin faptul ca: - programarea structurata este dirijata de prelucrari, iar OOP de definirea obiectelor; - programarea structurata trateaza complexitatea si diversitatea printr-o structurare a datelor si prelucrarii lor, iar OOP se bazeaza pe studiul modelelor cat mai apropiate de obiectele reale si de modul de reprezentare cunoscut de programator.
Exista o serie de avantaje de ordin practic ale OOP: - se folosesc biblioteci si colectii de clase care maresc coeficientul de reutilizare a codului scris; - programatorul are garantia utilizarii unor proceduri scurte, inteligibile si corecte; - bibliotecile de clase se mai pot folosi si in realizarea prototipurilor unor produse software (un program simplificat, functional, care da o imagine corecta a produsului final).
|
|