Skip to content

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
tgpetrica committed May 19, 2022
1 parent 6fa9c28 commit 5206560
Show file tree
Hide file tree
Showing 2 changed files with 161 additions and 1 deletion.
155 changes: 155 additions & 0 deletions POO_22_C_2022-05-19.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
## Mostenire multipla
C++ este unul dintre putinele limbaje de programare care accepta mostenire multipla, adica o clasa mosteneste mai multe clase. Clasele mostenite se enumera separate prin virgula dupa caracterul `:`, specificand in fata fiecarei clase modul in care acea clasa este mostenita: `public`, `protected`, `private` si optional specificatorul `virtual`.

![Imagine: mostenire multipla](https://cdn.discordapp.com/attachments/788436277388247050/976866983956074506/mostenire-multipla.png)

```cpp
class C: public A, public B
{
...
C(...):A(...),B(...)
{...}
};
```
Inainte de crearea obiectul instanta `C` sunt create subobiectele instanta `A` si apoi celei instanta `B`.
Mostenirea multipla vine si cu probleme suplimentare. Problema cea mai cunoscuta este cea a "Diamantului" care apare atunci cand o clasa mosteneste mai multe clase si cel putin doua din cele mostenite au stramos comuni. La instantiere, facilitatile stramosului ajung in obiectul creat pe doua cai. De fapt, obiectul creat va avea doua subobiecte instanta stramosului.
![Imagine: mostenire multipla - problema Diamantului](https://cdn.discordapp.com/attachments/788436277388247050/976868351659896872/mostenire-multipla-diamant.png)
```cpp
class S
{
public:
void f(){cout << "f" << endl;}
}
class A: virtual public S
{};
class B: virtual public S
{};
class C: public A, public B
{};
void main()
{
C c;
}
```
La instantierea clasei `C` o data cu obiectul `c` apar doua obiecte instanta `A`, respectiv `B` si pentru fiecare dintre aceste ultime doua obiecte cate un subobiect `S`, adica in total 5 obiecte in memorie. Problema apare atunci cand din obiectul instanta `C` incercam sa apelam/utilizam o facilitate mostenita din clasa `S`, fie ea camp sau functie, adica, in exemplul nostru, problema apare la apelul `c.f();`. Din cauza ca in memorie exista doua subobiecte instanta `S`, compilatorul nu poate decide din care aceste subobiecte va apela functia `f()`, rezultand eroare la compilare.
Solutia consta in a mosteni clasa `S` virtual. Se spune astfel ca `S` este o **clasa virtuala** in ierarhie. In urma mostenirii virtuale a clasei `S`, la instantierea clasei `C` se va creea un singur subobiect `S` si in consectinta apelul `c.f();` nu mai genereaza eroare la compilare.

## Clase imbricate
Exista posibilitatea declararii unei clase in interiorul altei clase.
```cpp
class A
{
...
class B
{...};
...
};
```
In exemplul de mai sus, spunem ca `B` este **imbricata** in clasa `A`.
Clasa `B` nu are acces la membrii protejati sau privati din clasa `A` si nici invers.
O clasa o descriem imbricata in alta clasa in general atunci cand numai in implementarea clasei mari este necesara existenta unor obiecte instanta clasei imbricate. Putem insa instantia clasa imbricata din exterior folosind operatorul de rezolutie:
```cpp
A::B b;
```

```cpp
class C
{
...
class B
{...};
...
};
```
Cele doua clase, desi au acelasi nume, sunt diferite (`B` din `A` si `B` dn `C`).
```cpp
C::B
```

## Clase template
Pe langa functii template, C++ ofera ca suport de programare generica si *clase template* pentru care unul sau mai multe tipuri de date sunt generice (nespecificate atunci cand descriem clasa).
Inaintea unei clase template trebuie sa apara acea specificatie pe care am intalnit-o la functiile template si anume, cuvantul rezervat `template`, urmat de o lista de date generice, specificata intre `<` si `>`. In fata fiecarui tip generic, apare tipul rezervat `class`.

```cpp
template <class T1, class T2,...>
class A
{...};
```
Pentru a nu avea probleme la link-editare in Visual C++ trebuie sa implementam toate metodele in momentul descrierii clasei, ci nu separat in fisier `.cpp`.
Daca in cazul functiilor template nu era nevoie la apel sa indicam tipurile de date ce substituie tipurile generice, identificarea lor facandu-se pe baza tipurilor de date ale parametrilor, in cazul claselor template trebuie sa specificam de fiecare data, cand ne referim la ele, intre `<` si `>` tipurile de date ce inlocuiesc tipurile generice.
De exemplu, pentru clasa `A`, vom scrie:
```cpp
A<int,float,...>
```
(*A de `int` `float` `...`*)

```cpp
template <class T>
class Punct3D
{
T x, y, z;
public:
Punct3D(T X, T Y, T Z)
{x = X; y = Y; z = Z;}
T abs(){return x*x + y*y + z*z;}
};

void main()
{
Punct3D<int> p1(1,2,3);
cout << p1.abs() << endl;
Punct3D<float> p2(1,0.5,2);
cout << p2.abs() << endl;
}
```
Toate functiile membre unei clase template devin la randul lor functii template.

## Ierarhia `ios`
`ios` - *input output stream standard*
Ierarhia este pornita de clasa `ios`.
Clasa `ios` porneste ierarhia, contine o serie de facilitati comune intregii ierarhii, in schimb nu se instantiaza direct. Clase aflate pe pozitii mai jos se instantiaza efectiv pentru a prelucra fluxul.
Ierarhia `ios` foloseste instante de obiecte ale ierarhiei `streambuf` atunci cand fluxurile sunt prelucrate. Un obiect instanta din ierarhia `streambuf` gestioneaza buffer-ul atasat fluxului.
Din cauza ca atunci cand prelucram un flux prin intermediului unui obiect instanta clasei `ios` si implementarea claselor a fost facut incat un obiect `streambuf` este gestionat automat, nu este necesar sa cunoastem membrii claselor `streambuf`, fiind suficient a cunoaste membrii claselor `ios`. Din clasa `streambuf` sunt derivate clasele `filebuf` (fiind specializata pe buffere atasate fisierelor) si `strstreambuf` (fiind specializata pe buffere pentru stringuri).
Clasa `ios` are doi constructori: `ios()` si `ios(streambuf* buf)`.
Clasa `ios` contine urmatoarele campuri:
- `adjustfield`: este un camp constant static transmis de obicei in al doilea parametru al functiei `setf`; aceasta constanta este folosita pentru curatatea bitilor de formatare legati de aliniere (`left` sau `right`).
- `basefield`: este un camp static constanta de tip `long` si este folosit pentru caratarea bitilor de formatare pentru bazele de numeratie.
- `floatfield`: constanta statica de tip `long` pentru curatarea bitilor de formatare cu virgula mobila (reale).
- `bp`: memoreaza adresa buffer-ului atasat fluxului, adica obiectul instanta `streambuf`.
- `state`: este o valoare de tip `int` ce memoreaza starea fluxului; bitii acestui camp daca sunt `1` inseamna ca au aparut erori in prelucrarea fluxului si dau informatii cu privire la tipul erorii.
- `x_fill`: o valoare de tip `int` care este folosit pentru caracterul pentru umplerea spatiilor libere
- `x_flags`: o valoare de tip `long` ce retine bitii de formatare la scriere (aliniere, baze de numeratie, etc.)
- `x_precision`: o valoare de tip `long` care retine precizia de afisare in virgula mobila a numerelor reale, adica numarul de cifre exacte folosite la afisare.
- `x_width`: valoare `int` ce retine numarul de caractere pe care se face afisarea.

Campurile care nu sunt constante de mai sus nu sunt publice. Aceste campuri se modifica folosind functii ale clasei `ios` sau ale claselor derivate din `ios`.
Functiile membre clasei `ios`:
- `int bad()`: returneaza o valoare nenula atunci cand in prelucrarea fluxului au aparut erori; sunt interogati bitii `ios::badbit` si `ios::hardfail`.
- `int fail()`: returneaza o valoare nenula daca au aparut erori in prelucrarea fluxului, interogandu-se in plus fata de `int bad()` si bitul `ios::failbit`.
- `int good()`: returneaza `1` daca nu au aparut erori in prelucrarea fluxului.
- `void clear(int st=0)`: aduce fluxul din nou in stare buna; campul `state` al parametrului, implicit `0`, evident cand nu exista erori.
- `char fill()`: returneaza caracterul folosit pentru caracterul care umple spatiile libere, adica returneaza valoarea lui `x_fill`.
- `char fill(char c)`: seteaza noul caracter al lui `x_fill` cu valoarea lui `c` si returneaza vechiul caracter al `x_fill`.
- `long iosflags()`: returneaza valoare campului `x_flags`.
- `long iosflags(long f)`: seteaza noua valoare a lui `x_flags` cu valoarea lui `f` si returneaza vechea valoare a lui `x_flags`.
- `void init(streambuf* buf)`: specificam adresa unui buffer ce se ataseaza fluxului curent.
- `int precision()`: returneaza precizia de afisare a numerelor reale.
- `int precision(int p)`: seteaza precizia `x_precision` la valoarea lui `p` si se returneaza vechea valoare a lui `x_precision`.
- `stringbuf* rdbuf()`: returneaza adresa catre buffer-ul fluxului.
- `int rdstate()`: returneaza valoarea lui `state`.
- `int setstate(int s)`: campul `state` devine `s`.
- `long setf(long flags`: bitii `1` ai variabilei `x_flags` fac sa devina biti `1` pe pozitiile corespunzatoare in campul `x_flags` si se returneaza vechea valoare a campului `x_flags`.
- `long setf(long flags,long field)`: reseteaza bitii (ii face 0) din `x_flags` pe pozitiile indicate de bitii cu valoare `1` ai parametrului `field` si seteaza bitii din `x_flags` la valoarea `1` pe pozitiile in care bitii sunt `1` in parametrul `flags`, returnand valoarea campului `x_flags` inainte de modificare.
- `long unsetf(long l)`: bitii `1` ai variabilei `l` anuleaza setari din campul `x_flags`.
- `void sync_width_stdin()`: fluxul `ios` este sincronizat cu fluxul standard de intrare din C; sincronizarea incetineste executia.
- `ostream* tie()`: este returnata adresa fluxului legat de fluxul curent; de exemplu, fluxul `cin` este legat de `cout`.
- `ostream* tie(ostream* f)`: fluxul curent este legat de adresa data ca parametru, returnandu-se vechea legatura.
- `int width()`: returneaza valoarea campului `x_width`.
- `int width(int w)`: este setata lungimea la afisarea formatata, returnandu-se vechea lungime.
7 changes: 6 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,9 @@
#### [Curs 11](https://github.com/tgpetrica/POO-courses/blob/main/POO_22_C_2022-05-12.md)
- ```dynamic_cast```
- functii pur virtuale
- clase abstracte
- clase abstracte
#### [Curs 12](https://github.com/tgpetrica/POO-courses/blob/main/POO_22_C_2022-05-19.md)
- mostenire multipla
- clase imbricate
- clase template
- ierarhia ```ios```

0 comments on commit 5206560

Please sign in to comment.