-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #2 from tgpetrica/add_2022-03-10
init
- Loading branch information
Showing
1 changed file
with
184 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,184 @@ | ||
## FUNCTII INLINE | ||
|
||
O functie inline se implenteaza ca si o functie obisnuita, singura deosebire de implementare fiind data de faptul ca , in fata antetului functiei se pune cuvantul rezervat ```inline```. Spre deosebire de o functie obisnuita, o functie inline are proprietatea ca, apelul ei este inlocuit acolo unde este posibil cu corpul functiei. Din acest punct de vedere, o functie inline se aseamana cu o macrocomanda. Din cauza ca apelul este inlocuit cu corpul functiei obtinem astfel o optimizare din punct de vedere al vitezei de executie, dar, evident, codul obiect (executabil) creste in dimensiuni. | ||
|
||
```cpp | ||
inline int maxim(int x, int y) | ||
{ | ||
return x>y?x:y; | ||
} | ||
|
||
inline int suma (int a, int b) | ||
{ | ||
return a+b; | ||
} | ||
|
||
void main() | ||
{ | ||
int a = suma(1,2)*4; | ||
cout<<a; | ||
} | ||
``` | ||
In exemplul de mai sus pe ecran se afiseaza ```12```, deoarece suma ramane o functie si se manifesta ca atare. In cazul in care suma era o macrocomanda, evindent a devenea ```9```. | ||
Nu orice functie poate fi ```inline```. Mai exact, functiile in care apar instructiuni repetitive sau instructiunea throw nu pot fi functii inline. Daca o functie care contine astfel de instructiuni este declarata inline atunci, la compilare, specificatia inline este ignorata (declar si degeaba). In general, functiile „mici” si care se executa foarte des intr-o aplicatie merita a fi declarate inline. | ||
## SUPRAINCARCAREA OPERATORILOR | ||
Una dintre cele mai interesante facilitati de redactare a codului oferite de C++ este data de posibilitatea de a Supraincarca operatorii, care nu este posibila in multe alte limbaje de programare consacrate. Marea majoritate a operatorilor din C++ pot fi Supraincarcati, adica definiti pentru alte tipuri de date decat cele pentru care exista deja implementati. Cel putin unul dintre operanzi trebuie sa fie de tipul class, struct sau enum. | ||
In C++ exista operanzi unari, binari si un singur operator ternar (```?:```). | ||
Aritatea operatorului reprezinta numarul de operanzi pentru care acel operator este definit. | ||
Singurul operatorul ternar nu poate fi supraincarcat, asadar, operatorii ce pot fi supraincarcati au aritatea 1 sau 2. Dintre acestia, urmatorii operatori nu pot fi supraincarcati: ```x::y``` , ```##```, ```x.y``` , ```x -> y``` | ||
Operatorii new si delete introdusi in C++, in plus fata de C, pot fi supraincarcati. | ||
La supraincarcare, operatorul isi pastreaza aritatea. Nu putem defini operatori noi. De exemplu ```**``` este un operator din Visual Basic, care nu exista in C++ si in consecinta nu poate fi supraincarcat. | ||
Supraincarcarea unui operator se face absolut similar cu descrierea unei functii C++, cu observatia ca, supraincarcarea operatorului presupune pentru numele functiei o combinatie intre cuvantul rezervat operator si simbolurile operatorului respectiv. | ||
```cpp | ||
float operator ^(float x, float y) | ||
{ | ||
return pow(x,y); | ||
} | ||
``` | ||
|
||
Supraincarcarea de mai sus este incorecta deoarece cel putin unul dintre operanzi trebuie sa fie de tipul class, struct sau enum. | ||
|
||
Supraincarcarea unui operator poate fi facuta in general intr-unul dintre urmatoarele doua moduri: | ||
|
||
- ca functie externa: numarul de parametri ai supraincarcarii trebuie sa fie egal cu aritatea operatorului. Exceptie de la aceasta regula fac 2 operatori: operatorul de post-incrementare si cel de post-decrementare, care, desi sunt unari au doi parametri. | ||
|
||
- ca functie membra unei clase sau unei structuri: numarul de parametri ai supraincarcarii este egal cu aritatea-1: cei unari nu au parametri, iar cei binari au un singur parametru. Exceptie fac post-incrementarea si post-decrementarea. | ||
|
||
### Supraincarcam operatori pentru urmatoarea structura: | ||
```cpp | ||
#define PI 3.14159 | ||
|
||
struct cerc | ||
{ | ||
float x,y,r; | ||
}; | ||
|
||
float arie (cerc c) | ||
{ | ||
return PI*c.r*c.r; | ||
} | ||
|
||
float operator !(cerc c) | ||
{ | ||
return PI*c.r*c.r; | ||
} | ||
|
||
/* | ||
Se observa ca functia arie si supraincarcarea operatorul ! sunt absolut similare ca si implementare si transmitere de parametri. Deosebirea si plusul adus de folosirea operatorului ! se vede atunci cand acesta este utilizat. | ||
*/ | ||
void main() | ||
{ | ||
cerc c; | ||
cin>>c.x>>c.y>>c.r; | ||
cout<<!c; // cout<<arie (c); | ||
} | ||
``` | ||
O data supraincarcat, un operator poate fi folosit sub forma sub care acesta a fost gandit in C++. | ||
La compilare, la intalnirea scrierii !c compilatorul cauta supraincarea operatorului ! pe care o gaseste ca fiind externa structurii cerc, iar aceasta scriere !c este inlocuita cu cout<< operator !(c) . Desi scrirea !c este echivalenta cu scrierea cout<< operator !(c) se prefera prima varianta tocmai pentru a usura scrierea codului. | ||
Supraincarcam operatorul ```+``` intre un cerc si un numar real rezultand un nou cerc , cu centrul in acelasi punct, dar cu raza mai mare. | ||
```cpp | ||
cerc operator +(cerc c, float dr); | ||
{ | ||
cerc c2; | ||
c2.r=c.r+dr; | ||
c2.x=c.x; | ||
c2.y=c.y; | ||
return c2; | ||
} | ||
``` | ||
|
||
Operatorul ```=``` poate fi supraincarcat, dar numai membrul unei clase sau structuri. In lista supraincarcarii lui ```=``` se face o supraincarcare implicita la compilare pentru structura, in care campurile operandului 1 se initializeaza cu valorile campului operandului 2. Astfel, scrierea ```c=c+2```; inseamna ca c primeste noul cerc c+2. | ||
|
||
Scrierea c+2 este echivalenta cu operator +(c,2) . De aici rezulta ca supraincarcarea lui + nu este comutativa. Scrierea 2+c este echivalenta cu operator + (2,c). Aceasta regula se pastreaza pentru toti operatorii binari, adica daca sunt comutativi, in urma supraincarcarii ei nu devin tot comutativi. Pentru a putea scrie si supraincarcarea | ||
```cpp | ||
cerc operator +(float dr, cerc c) | ||
{ | ||
return c+dr; | ||
} | ||
|
||
//Compararea a doua cercuri: | ||
|
||
int operator < (cerc c1, cerc c2) | ||
{ | ||
return c1.r < c2.r; | ||
} | ||
|
||
//SAU | ||
|
||
bool operator < (cerc c1, cerc c2) | ||
{ | ||
return c1.r < c2.r; | ||
} | ||
``` | ||
|
||
Supraincarcam operatorul ++ sub forma pre-incrementare, respectiv post-incrementare | ||
|
||
### Supraincarcarea pre-incrementarii: | ||
|
||
c++ si respectiv ++c vor mari raza cercului c cu o unitate. | ||
```cpp | ||
cerc oprator ++ (cerc &c) | ||
{ | ||
//pre-incrementare | ||
++c.r; | ||
return c; | ||
} | ||
|
||
/* | ||
Pentru a face distinctie intre pre-incrementare si post-incrementare, la post-incrementare se pune un parametru suplimentar de tip int. Pentru acest parametru nu este nevoie sa dam denumire. | ||
*/ | ||
cerc operator ++ (cerc &c, int) | ||
{ | ||
//post-incrementare | ||
cerc c0=c; | ||
c.r++; | ||
return c0; | ||
} | ||
``` | ||
Parametrul int apare pentru ca semnatura supraincarcarii post-incrementare sa difere de semnatura pre-incrementarii. Stim ca in C++ avem posibilitatea de a supraincarca functii daca acestea difera prin numar de parametri sau tipuri de date. | ||
|
||
Supraincarcarea operatorului << pentru afisarea unui cerc pe ecran: vom supraincarca << pentru un flux de iesire si un cerc. Din cauza ca cout este de tip flux de iesire va functiona si afisarea cercului pe ecran. Pentru un flux de iesire avem definita o clasa denumita ostream care face parte din ierarhia ios. | ||
```cpp | ||
ostream& operator << (ostream &fl, cerc c) | ||
{ | ||
fl<<c.c<<" "<<c.y <<" "<<c.r; | ||
return fl; | ||
} | ||
``` | ||
In cazul in care fluxul cout este transmis prin valoare, atunci, in functie se primeste o copie a acestui flux. Eventuala trimitere de date in copia lui cout nu va avea ca efect tiparirea pe ecran, deci in implementarea operatorului << prin parametru trebuie sa primim fluxul transmis, ci nu o copie. De aceea, primul operator trebuie transmis prin referinta. | ||
|
||
Dupa ce un cerc este trimis in fluxul de iesire trebuie sa exista posibilitatea ca in acel flux sa putem trimite si alte date, tot cu operatorul <<, deci in urma aplicarii operatorului << intre un flux de iesire si un tip de date , rezultatul trebuie sa fie fluxul trimis in primul parametru, adica, in cazul nostru, o referinta ca ostream, adica tipul returnat trebuie sa fie ostream&. | ||
```cpp | ||
cout<<c<<endl; | ||
``` | ||
Supraincarcarea operatorului >> : pentru extragerea unui cerc din flux de intrate trebuie ca primul paramentru sa fie din clasa istream si valoarea returnata trebuie sa fie referinta catre istream, din aceleasi considerente pe care le-am prezentat in cazul operatorului <<. | ||
```cpp | ||
istream& operator >> (istream& fl, cerc& c) | ||
{ | ||
return fl>>c.x>>c.y>>c.r; | ||
} | ||
|
||
``` | ||
TPA: Supraincarcati pentru cerc operatorii: | ||
- intre 2 cercuri in care rezulta un nou cerc avand x1+x2 y1+y2 r1+r2 | ||
- intre un cerc si un numar real rezulta un nou cerc cu raza micsorata cu real unitati. | ||
```cpp | ||
> | ||
>= | ||
!= | ||
== | ||
~ //(not pe biti): ~c = 2*PI*r *lungimea cercului | ||
``` |