|
Politica de confidentialitate |
|
• domnisoara hus • legume • istoria unui galban • metanol • recapitulare • profitul • caract • comentariu liric • radiolocatia • praslea cel voinic si merele da aur | |
"TUTORUL" LUI C++ introducere in c++ | ||||||
|
||||||
1.1 Introducere f9q4qm ----------- 1.1.1 Iesire #include <stream.h> main() #include <stream.h> - include declaratii pentru facilitatile standard
de intrare/iesire aflate in stream.h. Se apeleaza cu litere mari CC. Daca programul este in fisierul hello.c, atunci se compileaza si se executa ca mai jos: $CC hello.c $a.out Hello, world $ 1.1.3 Intrare #include <stream.h> main() //converteste inch in cm Aint inch = 0; cout << "inches"; cin >> inch; cout << inch; cout << "in="; cout << inch*2.54; cout << "cm\n"; S Exemplu de executie Ultimii 4 operatori pot fi scrisi: cout << inch << "in=" << inch*2.54 << "cm\n"; 1.2 Comentariu 1.3 Tipuri si Declaratii 1.3.1 Tipuri fundamentale char short int long float double sizeof(char) <= sizeof(short) <= sizeof(int)
<= sizeof(long) <= sizeof(float) <= sizeof(double) const float pi =
3.14; const char plus = '+'; * -> pointer *const -> pointer constant & -> adresa ai -> vector () -> functie char* p; char *const q; char va10i; char c; I &(si) ^ | << >> se aplica la intregi Cea mai frecventa forma a unei instructiuni este o instructiune expresie; ea consta dintr-o expresie urmata de un punct si virgula. a = b*3+c; cout << "go go go"; lseek(fd, 0, 2); Instructiunea VIDA:; Blocuri: A a = b + 2; b++; #include <stream.h> main() //converteste din inch in cm si invers A const float fac = 2.54; float x, in, cm; char ch = 0; cout << "enter lenght:"; cin >> x >> ch; if(ch=='i') A //inch in = x; cm = x*fac; S else if(ch=='c') A //cm in = x/fac; cm = x; S else in = cm = 0; cout << in << "in=" << cm << "cm\n"; S Instructiunea SWITCH: switch(ch) A case 'i': in = x; cm = x*fac; break; case 'c': in = x/fac; cm = x; break; default: in = cm = 0; break; S Instructiunea WHILE: 1.5 Functii O functie este o parte denumita a programului care poate fi apelata din alte
parti ale programului atit de des, cit este nevoie. extern float pow(float, int); overload pow; int pow(int, int); double pow(double, double); Declaratia overload pow informeaza compilatorul ca se intentioneaza sa se foloseasca
numele pow pentru mai mult decit o singura functie. Un nume care se utilizeaza ca sa refere acelasi lucru in doua fisiere sursa trebuie sa fie declarat ca extern: extern double sqrt(double); extern istream cin; Este bine ca aceste declaratii sa se plaseze intr-un fisier si apoi acesta
sa se includa. De exemplu, daca declaratia pentru sqrt() este in math.h atunci putem scrie: //header.h extern char* prog_name; extern void f(); Fisierul main.c este programul principal: si fisierul f.c imprima sirul: 1.7 Clase Declaratiile dupa eticheta public specifica interfata; utilizatorul poate apela
cele 3 functii put(). Declaratiile ce se gasesc inaintea etichetei public specifica
reprezentarea unui obiect al clasei ostream. Numele buf si state pot fi utilizate
numai prin functiile put() declarate in partea public. unde sputc() este o functie care pune un caracter in streambuf. Prefixul ostream
este necesar pentru a distinge put() a lui ostream de alte apeluri ale lui put(). Operatorul -> se utilizeaza pentru a selecta un membru al unui obiect. 1.8 Operatorul overloadingClasa reala ostream defineste operatorul << pentru a-l face convenabil
sa scrie diferite obiecte cu o singura instructiune. defineste operatorul <<, ca membru al clasei ostream, asa ca s<<p
se interpreteaza ca s.operator<<(p) cind s este un ostream si p este un
pointer spre caractere. Operatorul << este binar, dar functia operator<<(char*)
pare la prima vedere sa aiba un singur argument; el totusi are de asemenea argumentul
standard implicit this. Utilizind setul de operatii furnizate cu membri publici ai clasei ostream, noi putem acum defini << pentru tipuri utilizator cum ar fi cel complex, fara a modifica declaratia clasei ostream: ostream operator<<(ostream s, complex z) // un complex are doua parti: real si imaginar // se scrie un complex ca (real, imag) A return s << "(" << z.real << "," << z.imag << ")"; S Intrucit operator<<(ostream, complex) nu este o functie membru, este
necesar sa explicitam argumentele ca sa fie binare. Se vor scrie valorile in
ordine corecta caci <<, ca si majoritatea operatorilor C++ se grupeaza
de la stinga la dreapta; adica a<<b<<c inseamna (a<<b)<<c. Ultima versiune a lui ostream din nefericire contine o eroare serioasa. Problema
este ca ostream este copiat de doua ori pentru fiecare utilizare a lui <<:
odata ca un argument si odata ca valoare returnata. Aceasta lasa starea nemodificata
dupa fiecare apel. Este nevoie de o facilitate pentru a pasa un pointer la ostream
mai degraba decit sa se paseze insasi ostream. Corpul functiei este neschimbat dar asignarea facuta lui s va afecta acum obiectul
dat ca argument. In acest caz, returnindu-se o referinta de asemenea se imbunatateste
eficienta, intru- cit modul evident de implementare a unei referinte este un
pointer si un pointer este mai ieftin sa fie transferat decit o structura mare. Sa observam ca se folosesc doua operatii separate pentru a citi intr-o zona long si intr-o zona int si numai una pentru scriere. Motivul este ca un int poate fi convertit spre long prin regulile implicite de conversie. 1.10 Constructori 1.11 Vectori Conceptul de vector construit in C++ a fost proiectat pentru a permite o eficienta
maxima la executie si memorie minima. Este de asemenea, mai ales cind se utilizeaza
impreuna cu pointerii, un instrument puternic pentru construirea unor facilitati
de nivel inalt. Noi putem, totusi, sa ne plingem de faptul ca dimensiunea unui
vector trebuie sa fie specificata ca o constanta, ca nu exista verificarea depasirii
limitelor vectorilor, etc.. Un raspuns la aceste plingeri este: noi insine putem programa
acest lucru. Sa vedem daca acesta este un raspuns rezonabil, cu alte cuvinte,
sa testam facilitatile de abstractizare ale lui C++ incercind sa furnizam aceste
caracteristici pentru tipurile de vectori proiectati de noi si sa observam dificultatile
implicate, costurile implicate si comoditatea utilizarii tipurilor de vectori
rezultate. class vectorA int* v; int sz; public: vector(int); //constructor Functia size() returneaza numarul de elemente al vectorului; adica, indicii
trebuie sa fie in domeniul 0..size()-1. Functia set_size() este furnizata pentru
a schimba acea dimensiune, elem() furnizeaza acces la membri fara a verifica
indexul, iar operatorai furnizeaza acces cu verificarea limitelor. Noi putem declara vectori foarte asemanator cu vectorii care sint construiti in limbajul insusi: vector v1(100); vector v2(nelem*2-4); Operatia de acces poate fi definita ca: int& vector::operatorai(int i) Returnind o referinta se asigura ca notatia ai poate fi utilizata de ambele
parti a unei atribuiri: v1axi = v2ayi; ea va fi utilizata pentru a sterge operatorul si pentru a dezaloca spatiul alocat prin constructor, asa ca atunci cind un vector iese afara din domeniu, tot spatiul lui este eliberat si poate fi reutilizat. 1.12 Expandare inlineO functie membru nu este mai costisitoare la apel decit o functie nemembru
cu acelasi numar de argumente (sa ne amintim ca o functie membru totdeauna are
cel putin un argument), iar apelul functiilor C++ este aproximativ tot atit
de eficient ca si in alte limbaje. Totusi, pentru functiile extrem de mici,
apelul poate sa iasa in evidenta. Daca este asa, noi am putea dori sa specificam
o functie care sa expandeze in linie. In caz afirmativ, compilatorul va genera
cod propriu pentru functie in locul apelului. Semanticile apelului ramin neschimbate. De exemplu, daca size() si
elem() sint substituite in linie: vector s(100); Acum sa definim un vector pentru care un utilizator poate defini limitele indexului. class vec:public vectorA int low, high; public: vec(int,int); int& elem(int); int& operatorai(int); Constructia: (hb-lb+1) se utilizeaza pentru a specifica lista argument pentru constructorul clasei de baza vector::vector(). Acest constructor se apeleaza inaintea corpului lui vec::vec(). Iata un mic exemplu care poate fi executat daca se compileaza cu restul declaratiilor lui vector: #include <stream.h> void error(char* p) void vector::set_size(int) int& vec::operatorai(int i) main() 0 1 2 3 4 5 6 7 8 9 O alta directie a dezvoltarii este de a furniza vectori cu operatii: class Vec::public vectorA public: Observam modul in care constructorul pentru clasa derivata Vec::Vec() este
definit pentru a transfera argumentele lui la constructorul pentru clasa de
baza vector::vector(). Operatorul de atribuire este supraincarcat si poate fi
definit astfel: void Vec::operator=(Vec& a) Atribuirea de Vec-uri acum copiaza elemente, in timp ce atribuirea de vectori
copiaza pur si simplu structura care controleaza accesul la elemente. Acest constructor initializeaza un Vec ca o copie a altuia si va fi apelat
in cazurile mentionate precedent. Pentru operatori de forma = si +=, expresia
din stinga este evident speciala si se pare natural ca ei sa se implementeze
ca operatii asupra obiectelor notate prin acea expresie. In particular, este
posibil pentru ei sa se schimbe valoarea primului lor operand. Pentru operatori
de forma + si -, operandul sting nu necesita o atentie speciala. Noi am putea,
de exemplu, sa transferam ambele argumente prin valoare si totusi sa capatam
o implementare corecta a adunarii vectorilor. Vectorii pot fi mari, asa ca,
pentru a elimina copierea, operanzii lui + se transfera operatorului operator+()
prin referinta: Vec sum(s); for(int i=0; i<s; i++) sum.elem(i) = a.elem(i) + b.elem(i); return sum; S Iata un mic exemplu care poate fi executat daca se compileaza cu declaratiile
de vector prezentate anterior: Functia operator+() nu opereaza direct asupra reprezentarii unui vector; intr-adevar,
nu ar putea, deoarece nu este un membru. Totusi, uneori este de dorit ca sa
se admita ca functii nemembru sa aiba acces la partea privata a unui obiect
de clasa. De exemplu, neexistind functia cu acces "neverificat", vector::
elem(), noi ar trebui sa fortam verificarea indexului i fata de limitele vectorului
de trei ori de fiecare data cind se executa ciclul. Aceasta problema a fost
eliminata aici, dar ea este tipica, asa ca exista un mecanism pentru o clasa
care sa accepte accesul la partea sa privata pentru o functie nemembru. noi putem scrie: Un aspect particular util al mecanismului de prieten (friend) este ca o functie poate fi prieten a doua sau mai multe clase. Pentru a vedea aceasta, sa consideram definirea unui vector si a unei matrici si apoi definirea functiei de inmultire. 1.16 Vectori genericiNoi am dori, de exemplu, unul din acei vectori pentru tipul matrice pe care
l-am definit. Din nefericire, C++ nu furnizeaza o facilitate pentru a defini
o clasa vector cu tipul elementelor ca argument. Un mod de a proceda ar fi sa
se copieze atit definitia clasei cit si functiile membru. Acest lucru nu este
ideal, dar adesea este acceptabil. Noi putem utiliza macroprocesor pentru a
mecaniza acel task. De exemplu, clasa vector este o versiune simplificata a
unei clase care poate fi gasita intr-un fisier header standard. Noi am putea
scrie: Fisierul vector.h defineste macrouri asa ca declare(vector, int) se expandeaza
spre declaratia unei clase vector foarte asemanatoare cu cea definita, iar implement(vector,
int) se expandeaza spre definitiile functiilor acelei clase.Intrucit implement(vec-
tor, int) se expandeaza in definitii de functii, el poate fi utilizat numai
odata intr-un program, in timp ce declare(vector, int) trebuie sa fie utilizat
odata in fiecare fisier care manipuleaza acest fel de vectori intregi. declare(vector, int); O alta varianta ar fi ca sa definim vectorul nostru si cu alte clase container in termenii unor pointeri la obiectele unei anumite clase: class commonA /*........*/S; class vectorA common** v; //...... public: cvector(int); common*& elem(int); common*& operatorai(int); //...... S; Sa observam ca deoarece pointerii si nu obiectele insasi sint memorati intr-un
astfel de vector, un obiect poate fi "in" diferiti astfel de vectori
in acelasi timp. Aceasta este o caracteristica foarte utila pentru clasele container
de felul vectorilor, listelor inlantuite, multimilor, etc.. Mai mult decit atit,
un pointer la o clasa derivata poate fi atribuit la un pointer spre clasa ei
de baza, asa ca cvector de mai sus poate fi utilizat pentru a pastra pointeri
spre obiectele tuturor claselor derivate din common. De exemplu: class apple : public commonA /*...*/ S; class orange : public commonA /*...*/ S; class apple_vector : public cvectorA public: cvector fruitbowl(100); Totusi, tipul exact al unui obiect intr-o astfel de clasa container nu mai
este cunoscut de compilator. De exemplu, in exemplul precedent noi stim ca un
element al vectorului este un common, dar este un apple sau un orange ? In mod
obisnuit, tipul exact trebuie sa fie descoperit mai tirziu pentru a putea utiliza
corect obiectul. Pentru a face aceasta, noi trebuie sau sa memoram o anumita
forma a tipului de informatie in obiectul insusi sau sa ne asiguram ca numai
obiectele unui tip dat se pun in container. Ultima varianta este atinsa trivial
utilizind o clasa derivata. De exemplu, noi am putea face un vector de pointeri
apple: class apple_vector : public cvectorA public: apple*& elem(int i) Sa consideram scrierea unui program pentru afisarea formelor pe un ecran. Atributele comune ale formelor se reprezinta prin clasa shape, atribute specificate prin clase derivate specifice: class shapeApoint center; color col; //....... public: void move(point to) A center = to; draw(); S point where()A return center; S virtual void draw(); virtual void rotate(int); //........ S; Functiile care pot fi definite fara cunostinte despre forma specifica (de exemplu move si where), pot fi declarate in mod obisnuit. Restul se declara virtual, adica se vor defini intr-o clasa derivata. De exemplu: class circle : public shapeA int radius; public: void draw(); void rotate(int i)AS //....... S; Acum daca shape_vec este un vector de forme, noi putem scrie: for(int i=0; i<no_of_shapes; i++) shape_vecaii.rotate(45); pentru a roti (si redesena) toate formele cu 45 de grade. Acest stil este deosebit de util in programe interactive cind obiectele de tipuri diferite sint tratate uniform de catre softwareul de baza. |
||||||
|
||||||
|
||||||
Copyright© 2005 - 2024 | Trimite document | Harta site | Adauga in favorite |
|