Skip to content

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
tgpetrica committed May 12, 2022
1 parent a7f790d commit 33606e1
Show file tree
Hide file tree
Showing 2 changed files with 143 additions and 1 deletion.
138 changes: 138 additions & 0 deletions POO_22_C_2022-05-12.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
## `dynamic_cast`
Operatorul `dynamic_cast` este folosit pentru a converti un obiect de la o anumita adresa la un alt obiect. Obiectele trebuie sa fie instanta aceleiasi ierarhii. Mai mult, unul dintre obiecte trebuie sa fie subobiect al unuia dintre obiecte.
```cpp
class Persoana
{
char nume[50];
public:
Persoana(const char* nume){strcpy(nume,nume);}
virtual char* getNume(){return nume;}
virtual ~Persoana(){}
};
class student:public Persoana
{
char matricol[20];
public:
student(const char* nume, const char* matricol):Persoana(nume){strcpy(matricol, nrm);}
char* getMatricol(){return matricol;}
};

class profesor:public Persoana
{
int vechime;
public:
profesor(const char* nume, const int v):Persoana(nume),vechime(v){}
int getVechime(){return vechime;}
};

void main()
{
int n;
cin >> n;
Persoana** pers = new Persoana*[n];
for(int i = 0; i < n; i++)
switch(rand(time(0))%3)
{
case 0: cin >> nume; pers[i] = new Persoana(nume): break;
case 1: cin >> nume >> matricol; pers[i] = new student(nume, matricol); break;
case 2: cin >> nume >> v; pers[i] = new profesor(nume, v);
}
/*
* Pentru vectorul pers, dupa ce a fost creat, dorim
* ca pentru fiecare componenta sa stim ce instantiere
* s-a facut (persoana, student sau profesor).
* Daca cunoastem acest lucru, pentru studenti si
* pentru profesori vom avea informatii suplimentare
* (numar matricol, respectiv vechime).
* In C++ nu exista un mecanism de a afla ce tip de
* informatie se afla la o anumita adresa, deci in
* exemplul nostru, pers[i] nu stim daca este instanta
* persoana, student sau profesor.
* In cazul in care o clasa in intregime sau cel putin
* o functie membra este virtuala informatii despre un
* un obiect instanta acelei clase se retin in VMT. Pe
* baza acestor informatii se poate identifica ce
* obiecte avem in memorie instanta clasei respective.
* Acest lucru se poate obtine apeland la operatorul
*
* dynamic_cast
*
*
*/

...

for (int i = 0; i < n; i++)
if(dynamic_cast<student*>(pers[i]) != nullptr)
cout << "student" << endl;
else if(dynamic_cast<profesor*>(pers[i]) != nullptr)
cout << "profesor" << endl;
else
cout << "persoana" << endl;

/*
* dynamic_cast nu functioneaza (returneaza NULL), decat
* daca in clasa Persoana avem cel putin o metoda
* virtuala sau clasa este mostenita virtual.
*/

for(int i = 0; i < n; i++)
delete pers[i];
//daca nu avem destructor virtual in Persoana avem
//memory leak
delete[] pers;

}
```

```cpp
student *s = dynamic_cast<student*>(pers[1]);
```
Operatorul `dynamic_cast` se foloseste ca in exemplul de mai sus. Se incearca a se converti pointerul `pers[1]` la tipul `student*`. Acest lucru va fi posibil numai daca pentru `pers[i]` va exista si obiectul aferent instanta student (`pers[i]` s-a initializat cu un apel `new student`). In caz de reusita, operatorul returneaza pointerul catre obiectul `student` aflat in memorie.

## Functii pur virtuale si clase abstracte
O functie membra unei clase poate fi declarata ca fiind pur virtuala. Evident, aceasta functie este virtuala.
```cpp
class ...
{
virtual tip_returnat functieMembra (param) = 0;
}
```
O functie pur virtuala se recunoaste din faptul ca, dupa antetul ei, declarat virtual, apare specificatia ` = 0;`. O functie pur virtuala nu se implementeaza. O clasa care contine cel putin o functie pur virtuala devine **clasa abstracta**. O clasa abstracta nu poate fi instantiata. Clasele derivate dintr-o clasa abstracta, daca nu implementeaza toate functiile pur virtuale devin la randul lor clase abstracte. In Java trebuie scris `abstract`.
O clasa poate fi instantiata daca nu are functii pur virtuale si a implementat toate functiile pur virtuale mostenite, dintr-o eventuala clasa abstracta (mostenire directa).
O clasa care contine numai functii pur virtuale (ca metode) devine **interfata**.
O clasa abstracta, de obicei, descrie o ierarhie, trasand specificul acelei ierarhii. O clasa poate intra in ierarhia respectiva numai daca implementeaza toate metodele (specifice ierarhiei) clasei abstracte.
De exemplu: ierarhie figura geometrica. O clasa poate fi introdusa in aceasta ierarhie numai daca are metode pentru arie si perimetru. Cu alte cuvinte, oricine are arie si perimetru este figura geometrica. Ierarhia o deschidem cu o clasa abstracta avand cele doua metode pur virtuale.
```cpp
class FigGeom
{
char denumire[50];
public:
void setDen(char* den){strcpy(denumire, den);}
virtual float arie() = 0;
virtual float perimetru() = 0;
};
class Dreptunghi:public FigGeom
{
float x1, y1, x2, y2;
public:
Dreptunghi(float X1, float Y1, float X2, float Y2)
{
setDen("Dreptunghi");
x1 = X1;
y1 = Y1;
x2 = X2;
y2 = Y2;
}
float arie(){return fabs((x2-x1)*(y2-y1));}
float perimetru(){return (fabs(x2-x1)+fabs(y2-y1))+2.f;}
};
```
TPA: Sa se implementeze ierarhia FigGeom din imaginea urmatoare:

![Imagine: ierarhia FigGeom](https://cdn.discordapp.com/attachments/788436277388247050/974349459804815420/ierarhie-FigGeom.png)
Pentru fiecare trebuie sa implementati arie si perimetru.
Pornind de la ierarhia de mai sus putem oricand creea oricand un vector de figuri geometrice care contine obiecte (pointeri catre) instanta claselor derivate direct sau indirect din FigGeom.
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,8 @@
- functii virtuale
- mecanismul de apelare a functiilor virtuale
- destructori virtuali
- apelul unui constructor dintr-o clasa derivata
- apelul unui constructor dintr-o clasa derivata
#### [Curs 11](https://github.com/tgpetrica/POO-courses/blob/main/POO_22_C_2022-05-12.md)
- ```dynamic_cast```
- functii pur virtuale
- clase abstracte

0 comments on commit 33606e1

Please sign in to comment.