|
Politica de confidentialitate |
|
• domnisoara hus • legume • istoria unui galban • metanol • recapitulare • profitul • caract • comentariu liric • radiolocatia • praslea cel voinic si merele da aur | |
Concepte de baza ale limbajului C++ | ||||||
|
||||||
Modalitatile (tehnici, paradigme) de programare au evoluat de-a lungul anilor,
reflectand trecerea de la programe de dimensiuni reduse la programe si
aplicatii de dimensiuni foarte mari, pentru coordonarea carora sunt necesare
tehnici evoluate. j3l4lk Software-ul de dimensiuni mari, care nu poate fi realizat de o singura persoana, intra in categoria sistemelor complexe, alaturi de alte sisteme complexe din cele mai variate domenii, cum sunt organizarea materiei sau organizarile sociale. Situatiile reale si experiente ale psihologilor au relevat limitele capacitatii umane in perceptia sistemelor complexe, adica imposibilitatea unei persoane de percepe si controla un numar mare de entitati de informatie simultan. De aceea, descompunerea si organizarea sistemelor complexe, in scopul de putea fi percepute, proiectate sau conduse este esentiala. Ordinea in sistemele complexe este introdusa in general printr-o organizare ierarhica, pe mai multe tipuri si nivele de ierarhie. In reprezentarea ierarhica a sistemelor complexe se evidentiaza doua tipuri de ierarhii: ierarhia structurala sau de compozitie si ierarhia de tip. Ierarhia structurala este o ierarhie in care se poate afirma despre un obiect ca este o parte a altui obiect, mai complex. Exemple de astfel de descompuneri se pot da oricate, din orice domeniu. De exemplu, un calculator poate fi studiat prin descompunerea lui in subansamble componente: placa de baza, placa video, monitor, etc; la randul ei, placa de baza este compusa din placheta de circuit imprimat, procesor, memorie, etc. Aceasta este o ierarhie de tipul “este o parte din…”. Pe de alta parte, fiecare obiect poate fi incadrat intr-o categorie (clasa, tip) mai larga, care contine mai multe obiecte care au proprietati comune. De exemplu, procesorul este de o componenta electronica; monitorul este un dispozitiv de afisare, etc. Aceasta ierarhie se refera la apartenenta obiectelor la o anumita clasa (sau tip - “este de tipul…”). Este esential de a privi sistemele complexe din ambele perspective, studiindu-le atat din perspectiva ierarhiei structurale, deci a obiectelor care le compun, cat si a ierarhiei de tip, deci a claselor carora le apartin. La randul lor, clasele din care fac parte obiectele pot fi organizate sau studiate ca elemente componente ale unei ierarhii, prin care o clasa este considerata ca primitiva (parinte) a unei alte clase. Cele doua tipuri de ierarhii, ierarhia de clase si ierarhia de obiecte nu sunt independente, si, impreuna, pot sa reprezinte un sistem complex. La fel ca oricare sistem complex, software-ul poate fi controlat prin descompunerea lui. Rolul descompunerii unui sistem in general (si al programelor in special) este de a permite intelegerea si manevrarea acestuia: sistemul este descompus in parti din ce in ce mai mici, fiecare dintre ele putand fi rafinata si dezvoltata independent. Principiul “divide-et-impera”, care se aplica in multe situatii, este util si in programare. Se pot identifica doua tipuri de descompunere a programelor: descompunerea
algoritmica si descompunerea orientata pe obiecte. Modul in care este abordata programarea din punct de vedere al descompunerii programelor defineste mai multe tehnici de programare (paradigme), care s-au dezvoltat si au evoluat odata cu evolutia sistemelor de calcul. Programarea procedurala este prima modalitate de programare care a fost si este inca frecvent folosita. In programarea procedurala accentul se pune pe descompunerea programului in proceduri (functii) care sunt apelate in ordinea de desfasurare a algoritmului. Limbajele care suporta aceasta tehnica de programare prevad posibilitati de transfer a argumentelor catre functii si de returnare a valorilor rezultate. Limbajul Fortran a fost primul limbaj de programare procedurala. Au urmat Algol60, Algol68, Pascal, iar C este unul din ultimile inventii in acest domeniu. Programarea modulara. In cursul evolutiei programarii procedurale accentul
in proiectarea programelor s-a deplasat de la proiectarea procedurilor
catre organizarea datelor, aceasta deplasare reflectand cresterea dimensiunilor
programelor. O multime de proceduri corelate, impreuna cu datele pe care
le manevreaza sunt organizate ca un modul. Tehnica de programare modulara decide
descompunerea unui program in module, care incorporeaza o parte
din datele programului si functiile care le manevreaza. Aceasta tehnica este
cunoscuta ca tehnica de ascundere a datelor (data-hiding). In programarea
modulara stilul de programare este in continuare procedural si nu exista
o asociere stricta intre date si procedurile care opereaza asupra acestora,
ci doar gruparea in module cu posibilitatea de a ascunde anumite informatii
(date, nume de variabile, functii) definite intr-un modul, fata de celelate
module. Programarea orientata pe obiecte reprezinta aplicarea in domeniul programarii
a unei metode larg raspandite in tehnica, numita tehnologia orientata
pe obiecte, care se bazeaza pe modelul obiect. Modelul obiect al unei aplicatii
implica patru principii importante si anume: Programarea orientata pe obiecte-POO- (object-oriented programming) este o metoda de programare in care programele sunt organizate ca si colectii de obiecte cooperante, fiecare dintre ele reprezentand o instanta a unei clase oarecare, iar clasele sunt membre ale unei ierarhii de clase, corelate intre ele prin relatii de mostenire. Exista trei parti importante ale acestei definitii: Modelul obiect in domeniul programarii implica, pe langa implementarea programului intr-un limbaj anume, etape premergatoare de analiza si proiectare care pregatesc structurarea efectiva a programului. Analiza orientata pe obiecte este o metoda de analiza si examinare a unei aplicatii din perspectiva claselor si a obiectelor din domeniul problemei respective. Proiectarea orientata pe obiecte este o metoda de proiectare a sistemelor care implica descompunerea orientata pe obiecte si asigura o modalitate de reprezentare atat statica cat si dinamica a modelului sistemului proiectat. Produsele unei analize orientate pe obiecte servesc ca modele ale proiectarii orientate pe obiecte, iar rezultatele acesteia folosesc direct in programarea orientata pe obiecte. Ca suport al modelului final, orientat pe obiecte al unei aplicatii, programarea si limbajele orientate pe obiecte sunt acelea care se recomanda a fi studiate mai intai, pentru a beneficia de toate facilitatile si tehnicile puse la dispozitie prioectantilor, analistilor si programatorilor. Dintre limbajele de programare orientate pe obiecte, limbajul C++ este unul
dintre cele mai utilizate; compilatoare, biblioteci si instrumente de dezoltare
a programelor C++ sunt disponibile atat pentru calculatoare personale
cat si pentru cele mai dezvoltate sisteme si statii de lucru. Cel mai scurt program C++ este: main()A S #include <iostream.h> void main()A cout << “Hello, World!”<< endl; Prima operatie de scriere afiseaza la consola sirul Hello, World!, iar urmatoarea (endl) introduce caracterul de linie noua. Operatia de citire de la tastatura poate fi realizata in C++ printr-o instructiune care foloseste functia operator de citire >>. De exemplu, in instructiunile care urmeaza se citeste de la tastatura un numar intreg: int i; cin >> i; Desigur, functia scanf() de citire de la tastatura din limbajul C poate fi in continuare folosita, dar pe parcursul exemplificarilor se vor folosi mai mult aceste functii C++ de citire si de scriere la consola, iar descrierea detaliata a operatiilor de intrare-iesire din C++ este prezentata in sectiunea 6. Un program C++ consta dintr-unul sau mai multe fisiere (files). Un fisier este o bucata de text care contine cod sursa C++ si comenzi de preprocesare si este translatat din punct de vedere conceptual in mai multe faze. Prima faza este faza de preprocesare care executa includerea altor fisiere si substituirea macro-urilor. Preprocesarea este controlata prin intermediul directivelor introduse prin linii care au primul caracter #. Rezultatul preprocesarii este secventa de entitati (token -; semne). O astfel de secventa de entitati, adica un fisier rezultat dupa preprocesare, se numesste unitate de translatare (translation unit). 1.2 Conventii lexicale Exista cinci tipuri de entitati: identificatori (identifiers), cuvinte-cheie
(keywords), literale (literals), operatori (operators) si separatori (separators).
Caracterele: spatiu (blank), tabulatori orizontali si verticali (tabs), linie
noua (new line), caractere de formatare (formfeeds) si comentariile, numite
in ansamblu spatii albe (white spaces) sunt ignorate cu exceptia situatiei
cand folosesc pentru separarea entitatilor. Un spatiu alb este necesar
pentru separarea identificatorilor, a cuvintelor-cheie si a constantelor. Identificatori. Un identificator este o secventa de lungime oarecare de litere si cifre, cu conditia ca primul caracter sa fie litera sau caracterul de subliniere _ (underscore). Literele mici sunt diferite de literele mari corespunzatoare. Toate caracterele intr-un identificator sunt semnificative. Cuvinte-cheie. Urmatorii identificatori sunt rezervati pentru a fi utilizati ca si cuvinte-cheie, si nu pot avea alta utilizare: asm continuos float new signed try auto default for operator sizeof typedef break delete friend private static union case do goto protected struct unsigned catch double if public switch virtual char else inline register template void class enum int return this volatile const extern long short hrow while In plus, identificatori care contin doua caractere de subliniere (underscore) sau incep cu un astfel de caracter sunt utilizati in implementarile C++ si a bibliotecilor si se recomanda sa fie evitati. Literale (constante). Constantele se refera la valori fixe, pe care programul
nu le poate modifica. Exita mai multe feluri de constante: constante intregi,
constante caracter, constante reale si constante sir de caractere. Un nume (name) poate reprezenta un obiect, un tip, o enumeratie, o functie,
o multime de functii, un membru al unei clase, o valoare sau o eticheta. Un
nume este introdus in program printr-o declaratie (declaration). Un nume
poate fi folosit numai intr-o zona a programului, denumita domeniul numelui
(scope). • contine specificatorul extern fara o expresie de initializare sau corp
al functiei; De exemplu, urmatoarele sunt definitii: int a; extern const c = 1; int f(int x) Areturn x+1;S enum Aup, downS; in timp ce urmatoarele sunt doar declaratii: extern int a; extern const c; int f(int); struct S; typedef int Int; Trebuie sa existe o singura definitie a fiecarui obiect, functie, clasa sau enumeratie folosita in program. Daca o functie nu este niciodata apelata sau daca numele unei clase nu este niciodata folosit intr-un mod care sa necesite definitia acesteia, ele pot sa nu fie definite. O declaratie poate fi repetata de mai multe ori in program, in timp ce definitiile nu pot fi repertate. De exemplu: struct S; // corect, redeclarare struct S; // corect, redeclarare int a; int a; // eroare, redefinire Domeniu de vizibilitate. Un nume este vizibil in intregul sau domeniu de definitie daca nu este redefinit intr-un bloc inclus in domeniul respectiv. Daca intr-un bloc interior domeniului unui nume se redefineste (sau se redeclara) acelasi nume, atunci numele initial (din blocul exterior) este partial ascuns, si anume in tot domeniul redeclararii. De exemplu: void fv1() Un nume cu domeniu fisier poate fi accesat intr-un domeniu in
care este ascuns prin redefinire, daca se foloseste operatorul de rezolutie
pentru nume globale (operatorul :: fara nici un nume in fata lui). Durata de viata a obiectelor. Un obiect este creat atunci cand se intalneste
definitia lui (care este unica) si este distrus (in mod automat) atunci
cand se paraseste domeniul lui de definitie. Un obiect cu un nume global
se creaza si se initializeaza o singura data si are durata de viata pana
la terminarea programului. Obiectele locale se creaza de fiecare data cand
executia programului ajunge in punctul de definire a acestora, cu exceptia
variabilelor locale declarate de tip static. #include <iostream.h> int a = 0; // variabila globala, se initializeaza void main ()A for (int i=0;i<3;i++) f(); produce mesajele: a = 1 b = 2 c = 3 a = 2 b = 2 c = 5 a = 3 b = 2 c = 7 O variabila (obiect) globala sau statica, care nu este initializata explicit,
este initializata automat cu 0. Categorii de memorare. Exista patru specificatori de categorii de memorare
a obiectelor: auto, static, register, extern. Fiecare nume intr-un program C++ are un tip asociat lui, care determina
ce operatii se pot aplica entitatii la care se refera acest nume. 1.4.1 Tipuri fundamentale In C++ sunt definite urmatoarele tipuri fundamentale: • Tipuri de intreg, pentru definirea numerelor intregi de diferite dimensiuni (ca numar de octeti ocupati in memorie): char 1 octet short int 2 octeti int 2 sau 4 octeti long 4 sau 8 octeti • Tipuri de numere flotante, pentru definirea numerelor reale (reprezentate ca numere cu virgula flotanta): float 4 octeti double 8 octeti long double 12 sau 16 octeti Aceste tipuri sunt denumite impreuna tipuri aritmetice. Pentru tipurile intreg, exista variante de declaratie cu semn (signed) si fara semn (unsigned). • Tipul void specifica o multime vida de valori. Nu se poate declara un obiect cu acest tip, dar acest tip poate fi utilizat in conversii de pointeri si ca tip de returnare a unei functii 1.4.2 Tipuri derivate Se pot defini conceptual un numar infinit de tipuri derivate pornind de la tipurile fundamentale. Tipurile derivate sunt: • tablouri de obiecte, In continuare se vor prezenta primele cinci tipuri derivate, iar celelate vor fi introduse pe parcursul sectiunii urmatoare. Ca terminologie, clasele (impreuna cu structurile si uniunile) sunt denumite tipuri definite de utilizator (user-defined types), iar celelate tipuri sunt denumite tipuri predefinite (built-in types) 1.4.2.1 Tablouri de obiecteUn tablou (array) de obiecte poate fi construit din obiecte dintr-un tip fundamental
(cu exceptia tipului void), din pointeri, din enumeratii sau din alte tablouri.
In traducere, pentru array se mai intalnesc termenii vector
si matrice. In acest text sunt folositi termenii tablou (pentru array
multidimensional) si vector (pentru array unidimensional). Intr-un mod asemanator se pot construi tablouri multidimensionale, cu o limitare a numarului de dimensiuni care depinde de impelementare. 1.4.2.2 Pointeri Pentru majoritatea tipurilor T, T* este un tip denumit “pointer la T”, adica o variabila de tipul T* memoreaza adresa unui obiect de tipul T. Operatia fundamentala asupra unui pointer este operatia de dereferentiere (dereferencing), adica accesarea obiectului a carui adresa o reprezinta pointerul respectiv. Operatorul de dereferentiere este operatorul unar *. De exemplu: char c1 = ‘a’; char* p1 = &c1; // p memoreaza adresa lui c1 char c2 = *p1; // dereferentiere, c2 = ‘a’; Operatorul & este operatorul adresa, care se utilizeaza pentru a se obtine
adresa unei variabile. int strlen(char* p)A int i = 0; Functia strlen() returneaza numarul de caractere ale sirului, fara caracterul terminal 0, folosind operatia de incrementare a pointerului si operatia de dereferentiere pentru a testa valoarea caracterului. O alta implementare posibila a functiei este urmatoarea: int strlen(char* p)A char* q = p; In C++, ca si in limbajul C, pointerii si tablourile sunt puternic corelate. Un nume al unui tablou poate fi folosit ca un pointer la primul element al tabloului. De exemplu, se poate scrie: char alphaai = “abcdef”; char* p = alpha; char* q = &alphaa0i; Rezultatul aplicarii operatorilor aritmetici +, -, ++, -- asupra pointerilor
depinde de tipul obiectului indicat. Atunci cand se aplica un operator
aritmetic unui pointer p de tip T*, se considera ca p indica un element al unui
tablou de obiecte de tip T; p+1 va indica urmatorul element al tabloului, iar
p-1 va indica elementul precedent al tabloului. Acest lucru inseamna ca
valoarea lui p+1 este cu sizeof(T) octeti mai mare decat valoarea lui
p. 1.4.2.3 Referinte O referinta (reference) este un nume alternativ al unui obiect. Utilizarea principala a referintelor este in specificarea argumentelor si a valorilor returnate de functii, in general si pentru supraincarcarea operatorilor in special. Notatia X& inseamna referinta la obiectul cu numele X. De exemplu: int i = 1; int& r = i; // r si i se refera la aceeasi entitate int x = r; // x = 1 r++; // i = 2; Implementarea obisnuita a unei referinte este printr-un pointer constant care
este dereferentiat de fiecare data cand este utilizat. int a = 5; int* pi = &a; // & calculeaza adresa; O referinta este utilizata ca argument pentru o functie care poate sa modifice valoarea acestui argument. De exemplu: void incr(int& x) Ax++;S void f()A int i = 1; incr(i); // i = 2; O alta utilizare importanta a referintelor este pentru definirea functiilor care pot fi folosite atat ca membru drept cat si ca membru stang al unei expresii de asignare. De exemplu: #include <iostream.h> int& fr(int vai, int i)A return vaii; La executia acestui program se obtine mesajul: 1.4.2.4 Functii Functiile sunt tipuri derivate si reprezinta una din cele mai importante caracteristici ale limbajelor C si C++. Forma generala de definire a unei functii este: tip_returnat nume_func(tip1 arg1,tip2 arg2,……,tipn argn) A Functia cu numele nume_func returneaza o valoare de tip tip_returnat si are
un numar n de argumente formale declarate ca tip si nume in lista de argumente
formale. Argumentele formale din declaratia unei functii se mai numesc si parametrii
functiei. Daca o functia nu are argumente, atunci lista din parantezele rotunde
este vida. Notatia din C: f(void) este redundanta. Prototipurile functiilor. Pentru apelul unei functii este necesara cunoasterea
definitiei sau a prototipului acesteia. Prototipul unei functii este de forma: tip_returnat nume_func(tip1 arg1,……., tipn argn); double f2(int, double); // prototip functie f2 double f2(int a, double f)A // definitie functie f3 La compilare apare o eroare datorita apelului functiei f1(), care nu este definita, nici declarata prin prototip in domeniul functiei apelante fp() si o eroare datorat apelului functiei f3() cu un argument (argumentul al doilea) care nu poate fi convertit la tipul argumentului formal. Transferul argumentelor functiilor. La apelul unei functii, argumentele reale
(se mai numesc si efective) de apel initializeaza argumentele formale din declaratia
functiei, in ordinea din declaratie. Argumentele unei functii se pot transfera
in doua moduri: apelul prin valoare si apelul prin referinta. void swap(int* x, int* y)A int t; t = *x; // dereferentiere Aceeasi functie swap(), folosind argumente de tip referinta, arata astfel: void swap(int& x, int& y)A int t; t = x; x = y; y = t; Se poate observa perfecta simetrie intre cele doua implementari si ca,
in mod evident, referinta foloseste adresa variabilei pentru a o putea
modifica (deci un pointer). Dar, in cazul referintelor, pointerul si defererentierea
sunt ascunse, programatorul nu trebuie sa le introduca explicit, programul rezultat
este mai concis si mai clar. Argumente implicite ale functiilor. Se intampla frecvent ca o functie
sa aiba un numar mai mare de argumente decat sunt necesare in cazurile
simple dar frecvente de apel. Daca nu este necesar sa fie transmisa intotdeauna
valoarea reala a unui argument si acesta poate lua, de cele mai multe ori, o
valoare implicita, atunci in declaratia functiei se prevede o expresie
de initializare a acestui argument, iar din apel poate sa lipseasca valoarea
argumentului corespunzator. struct dataA int zi; int luna; int an; Numai argumentele de la sfarsitul listei pot fi argumente implicite. De exemplu, este eronata urmatoarea declaratie: void setdata(int zi, int luna=9, int an); // eroare Pointeri la functii. Dat fiind ca o functie are o localizare in memorie,
aceasta valoare poate fi atribuita unui pointer. Adresa unei functiei este punctul
de intrare in functie si, de aceea, functia poate fi apelata folosind
un pointer. float func1(int x, float y)A return x + y; pf = func1; // definire valoare pointer float z = (*pf)(3, 1.2f); // apel functie cout << z << endl; // afiseaza 4.2 pf = func2; // definire valoare pointer z = (*pf)(3, 1.2f); // apel functie cout << z << endl; // afiseaza 3.6 Desi din acest exemplu simplu nu reiese care ar putea fi avantajul folosirii apelului prin pointer a unei functii, exista totusi situatii cand apelul prin pointeri este mai avantajos. De exemplu, poate sa fie inlocuita o instructiune switch care selecteaza dintre mai multe apeluri de functii, cu un vector de functii care se pot apela prin pointerii corespunzatori. Supraincarcarea functiilor. In limbajul C, fiecare functie definita
in program trebuie sa aiba un nume diferit. In C++, mai multe functii
pot avea acelasi nume in acelasi domeniu de definitie, daca se pot diferentia
prin numarul sau tipul argumentelor de apel. Acest mecanism se numeste supraincarcarea
functiilor (function overloading). In traducere, se mai intrebuinteaza
si denumirile de suprapunere, redefinire, supradefinire; in textul de
fata este preferat termenul de supraincarcare. Supraincarcarea se
poate aplica atat functiilor cat si operatorilor; in sectiunea
aceasta este prezentata supraincarcarea functiilor, iar supraincarcarea
operatorilor este descrisa in sectiunea 4. double abs(double); int abs(int); abs(1); // apeleaza abs(int) abs(1.0); // apeleza abs(double) Acceptarea mai multor versiuni ale unei functii cu acelasi nume este conditionata
de posibilitatea selectarii fara ambiguitate a uneia dintre acestea dupa tipul
sau numarul argumentelor. Nu este admis ca functiile sa difere doar prin tipul
returnat. int f(char*); void g()A extern f(int); f(“abcd”); // eroare, f(int) ascunde f(char*) Situatii asemanatoare, de ascundere si nu de supraincarcare in
domenii diferite vor mai fi prezentate in sectiunea 5, dedicata claselor
derivate. int power(int, int); long power(long,int); double power(double, int); double power(double, double); In apelurile: power(7, 8); // selecteaza power(int, int) power(5.6, 2); // selecteaza power(double, int) power(6.7, 2.5); // selecteaza power(double, double) versiunea functiei power() este selectata pe baza coincidentei dintre argumentele
de apel si argumentele formale. long a = 100; int b = 10; float c = 2.3f; float d = 5.6f; double e = 7.0; double f = 2; power(a,b); // selecteaza power(long, int) power((int)a, b); // selecteaza power(int, int) power(c,a); // selecteaza power(double, int) power(c,d); // selecteaza power(double, double) power(e,d); // selecteaza power(double, double) Daca prin astfel de conversii nu se poate stabili cea mai buna potrivire a argumentelor, atunci sunt incercate si conversii pentru tipuri definite de utilizatori. Apelul este acceptat numai daca selectia unei versiuni a functiei (pe baza criteriului de cea mai buna potrivire a argumentelor) este unica. Conversiile intre date de tipuri definite de utilizatori sunt prezentate in sectiunea 4, dedicata supraincarcarii operatorilor. 1.4.2.5 Constante simbolice O constanta simbolica (sau constanta cu nume) este un nume a carui valoare nu poate fi modificata in cursul programului. In C++ exista trei modalitati de a defini constante simbolice: • Orice valoare, de orice tip care poate primi un nume, poate fi folosita
ca o constanta simbolica prin adaugarea cuvantului-cheie const in
declaratia acesteia. • O multime de constante intregi poate fi definita ca o enumeratie. De exemplu, urmatoarele declaratii introduc constante simbolice prin folosirea cuvantului-cheie const: const int val = 100; const double dai = A1.2, 2.8, 9.5S; Deoarece constantele nu pot fi modificate, ele trebuie sa fie initializate in declaratie. Incercarea de modificare ulterioara este detectata ca eroare in timpul compilarii: val++; // eroare d = 200; // eroare Cuvantul-cheie const modifica tipul obiectului, restrictionand
modul in care acesta poate fi folosit. const char* pc = “abcd”;// pc este pointer la o constanta pca2i = ‘m’; // eroare, nu se poate modifica Pentru ca pointerul insusi sa fie constant, se foloseste operatorul *const: char *const cp = “abcd”;// cp este pointer constant; cpa2i = ‘m’; // corect, modifica valoarea cp = ++; // eroare, pointer constant Posibilitatea de declarare a pointerilor la constante este intens folosita
in transmiterea argumentelor functiilor. Prin declararea unui argument
de tip pointer la constanta, este interzisa modificarea de catre functie a obiectului
indicat. De exemplu: char* strcpy(char* d, const char* s); Enumeratii. O alta metoda de a defini constante intregi este prin enumeratie. De exemplu, enumeratia: enum A este echivalenta cu declararea urmatoarelor constante: const INPUT = 0; const OUTPUT = 1; const INOUT = 2; Valorile asignate implicit constantelor incep de la 0 si sunt in ordine crescatoare. Enumeratiile pot avea nume. De exemplu: enum statesA good, bad, fail Un nume declarat de tipul unei enumeratii poate lua orice valoare particulara
cuprinsa in enumeratie. enum statesA good = 0x00, bad = 0x01, fail = 0x10 1.4.2.6 Specificatorul typedef Declaratiile care contin cuvantul-cheie typedef declara identificatori care pot fi folositi pentru denumirea tipurilor fundamentale sau derivate in domeniul de definitie al acestuia. O declaratie care contine specificatorul typedef nu introduce nume noi in program, ci realizeaza o echivalenta sintactica a unui nou nume cu un alt nume, fundamental sau derivat. De exemplu, in declaratiile: typedef int KM, *PKM; KM este de tip intreg, iar pd este pointer la intreg. typedef struct A /*……*/S S; //structura este denumita S. Acesta este modul obisnuit de declaratie in C, unde numele unei structuri nu poate fi folosit ca un nume de tip fara sa fie insotit de cuvantul-cheie struct. Acest stil este admis si in C++, pentru a se asigura compatibilitatea. Dar stilul mai normal pentru C++ este de a declara o structura cu nume si fara typedef: struct SCA/*...*/S; 1.4.2.7 Specificatorul volatile Specificatorul volatile indica faptul ca valoarea obiectului poate fi modificata pe alte cai decat cele declarate explicit in program. De exemplu, adresa unei variabile globale poate fi transmisa unei rutine de interfata a sistemului, care modifica valoarea acesteia, fara o instructiune explicita din program. Acest lucru este important, deoarece majoritatea compilatoarelor de C si C++ optimizeaza automat evaluarea expresiilor prin presupunearea ca o variabila ramane neschimbata atata timp cat nu apare in partea stanga a unei operatii de asignare. Specificatorul volatile impiedica aplicarea unor astfel de optimizari. 1.4.2.8 Clase, structuri, uniuni Pe langa tipurile de date fundamentale ale limbajului, in C++ se pot defini tipuri de date noi prin definirea unor clase. Aceste tipuri se numesc tipuri definite de utilizator (user-defined types) si se pot utiliza intr-un mod asemanator utilizarii tipurilor predefinite. Aceste tipuri mai sunt denumite si tipuri de date abstracte (abstract data types), dar in aceasta lucrare s-a preferat termenul de tip definit de utilizator, asa cum il prefera autorul limbajului aStroustrup 94i. De exemplu, declaratia: class XA este si o definitie a clasei X, care introduce un tip nou de date. Prin aceasta
definitie se asociaza numele X cu entitatea definita in corpul clasei.
Dupa definirea unui astfel de tip de date, se pot declara (defini) obiecte de
tipul respectiv, la fel ca si variabilele (obiecte) de tipuri predefinite: O expresie este o secventa de operatori si operanzi care specifica executarea
unor calcule. O expresie poate produce un rezultat sau efecte laterale (side
effects). Majoritatea operatorilor C++ sunt preluati din limbajul C, cu aceeasi sintaxa si reguli de operare. In plus fata de operatorii C, in C++ mai sunt introdusi urmatorii operatori: • operatorul de rezolutie (::), Operatorul de lansare exceptie (throw) este descris in sectiunea 8. Ceilalti operatori sunt descrisi in continuare. 1.5.1.1 Operatorul de rezolutie Operatorul de rezolutie (::) este folosit pentru modificarea domeniului de vizibilitate al unui nume. Pentru acest operator (scope resolution operator), in traduceri se mai intalnesc termenii de operator de domeniu sau operator de acces. Operatorul de rezolutie permite folosirea unui identificator intr-un bloc in care el nu este vizibil. Daca operatorul de rezolutie nu este precedat de nici un nume de clasa, atunci este accesat numele global care urmeaza acestui operator. De exemplu: int g = 10; int f()A int g = 20; return ::g; In acest exemplu operatorul de rezolutie a fost folosit pentru a accesa variabila globala g, ascunsa de variabila locala cu acelasi nume din functie. Deoarece utilizarea cea mai extinsa a operatorului de rezolutie este legata de utilizarea claselor, el va fi reluat pe parcursul sectiunilor urmatoare. 1.5.1.2 Operatorii de alocare-eliberare dinamica a memoriei. In limbajul C se pot aloca dinamic zone de memorie in memoria libera
(heap) folosind functii de biblioteca (de exemplu, malloc(), calloc(), realloc())
si se pot elibera folosind functia free(). La aceste posibilitati, care se pastreaza
in continuare in C++, se adauga posibilitatea folosirii operatorilor
de alocare si eliberare dinamica a memoriei, new si delete. Acesti operatori
unari prezinta avantaje substantiale fata de functiile de alocare din C si de
aceea sunt in mod evident preferati in programele scrise in
C++. int *pi = new int(3); // alocare int si initializare double *pd = new double; // alocare double neinitializat char *pc1 = new chara12i; // vector de 12 caractere char *pc2 = new chara20i; // vector de 20 caractere delete pi; delete pd; delete pc1; delete aipc2; In legatura cu existenta celor doua modalitati de alocare dinamica, prin operatorii new-delete sau prin functiile de biblioteca malloc-free, fara sa fie o regula precisa, combinarea acestora este bine sa fie evitata, deoarece nu exista garantia compatibilitatii intre ele. 1.5.2 Precedenta operatorilor In tabelul urmator sunt prezentati concis operatorii din limbajul C++ grupati in ordinea precedentei lor. In fiecare compartiment sunt trecuti operatorii cu aceeasi precedenta. Un operator dat are o precedenta mai ridicata decat un altul dintr-un compartiment aflat mai jos in tabel. Operatorii se aplica in ordinea precedentei lor. De exemplu, a+b*c inseamna a+(b*c), deoarece inmultirea (*) are o precedenta mai ridicata decat adunarea (+). Operatori C++:: operator rezolutie nume_clasa::membru :: nume global ::nume . selectie membru obiect.membru -> selectie membru pointer->membru ai indexare pointeraexpri () apel functie expr (lista_expr) () conversie explicita tip(list_expr) sizeof dimensiune obiect sizeof expr sizeof dimensiune tip sizeof (tip) ++ post incrementare lvalue++ ++ pre incrementare ++lvalue -- post decrementare lvalue- -- pre decrementare --lvalue I complement Iexpr ! negatie !expr - minus unar -expr + plus unar +expr & adresa &lvalue * derefentiere *expr new alocare new tip delete eliberare(dezalocare) delete pointer deleteai eliberare tablou deleteaipointer () conversie cast (tip)expr .* selectie membru obiect.*pointer_la_membru ->* selectie membru pointer->*pointer_la_membru * inmultire expr * expr / impartire expr / expr % modulo expr % expr + adunare expr + expr - scadere expr - expr << depl. logica stanga expr << expr |
||||||
|
||||||
|
||||||
Copyright© 2005 - 2024 | Trimite document | Harta site | Adauga in favorite |
|