Differences

This shows you the differences between two versions of the page.

Link to this comparison view

poo-is-ab:laboratoare:12 [2024/12/17 09:02]
razvan.cristea0106 [Rezolvarea Problemei Rombului]
poo-is-ab:laboratoare:12 [2025/01/19 22:31] (current)
razvan.cristea0106
Line 21: Line 21:
 {{ :​poo-is-ab:​laboratoare:​diamond.jpg?​direct&​400 |}} {{ :​poo-is-ab:​laboratoare:​diamond.jpg?​direct&​400 |}}
  
-Așa cum se poate observa și în imaginea de mai sus clasa **D** are două copii ale clasei **A**, ceea ce duce la **ambiguități** și **inconsistențe**. De exemplu, dacă încercăm să accesăm un membru al clasei **A** din clasa **D**, compilatorul **nu** poate determina ​pe unde să o ia, deoarece atât calea **D-B-A** cât și **D-C-A** duc spre clasa **A**.+Așa cum se poate observa și în imaginea de mai sus clasa **D** are două copii ale clasei **A**, ceea ce duce la **ambiguități** și **inconsistențe**. De exemplu, dacă încercăm să accesăm un membru al clasei **A** din clasa **D**, compilatorul **nu** poate determina ​care este drumul corect, deoarece atât calea **D-B-A** cât și calea **D-C-A** duc spre clasa **A**.
  
 În limbajele **C#** și **Java**, moștenirea multiplă a claselor **nu** este permisă tocmai pentru a evita astfel de probleme. În schimb, aceste limbaje oferă mecanisme alternative,​ precum **interfețele**,​ care permit implementarea a numeroase comportamente **fără** a introduce **conflicte** legate de **ambiguitatea moștenirii**. ​ În limbajele **C#** și **Java**, moștenirea multiplă a claselor **nu** este permisă tocmai pentru a evita astfel de probleme. În schimb, aceste limbaje oferă mecanisme alternative,​ precum **interfețele**,​ care permit implementarea a numeroase comportamente **fără** a introduce **conflicte** legate de **ambiguitatea moștenirii**. ​
Line 31: Line 31:
 ==== Rezolvarea Problemei Rombului ==== ==== Rezolvarea Problemei Rombului ====
  
-Pentru a putea gestiona și rezolva corect această problemă trebuie să aplicăm doi pași si anume: **derivarea virtuala a claselor intermediare din clasa de baza** și respectiv **testarea aplicației** pentru ​a vedea dacă se comportă în conformitate cu așteptările pe care le avem.+Pentru a putea gestiona și rezolva corect această problemă trebuie să aplicăm doi pași si anume: **derivarea virtuala a claselor intermediare din clasa de baza** și respectiv **apelarea constructorilor clasei de bază în lista de inițializare a constructorilor clasei nepot**. Pentru ​a vedea dacă aplicația ​se comportă în conformitate cu așteptările pe care le avem va trebui să o testăm constant pentru a vedea dacă am eliminat toate ambiguitățile generate de problema rombului.
  
 === Derivarea virtuală === === Derivarea virtuală ===
Line 114: Line 114:
 </​code>​ </​code>​
  
-<note warning>​Comportamentul descris mai sus apare din cauza **problemei rombului**, care generează o **ambiguitate** ce conduce la **dublul apel** al constructorului și destructorului clasei de bază **A**. Această situație poate deveni problematică în special în scenariile în care superclasa **A** gestionează resurse **alocate dinamic**. În astfel de cazuri, **ambiguitatea** poate duce la comportament nedefinit, cum ar fi **memory leaks** sau chiar **crash-uri** ale aplicației,​ deoarece **destructorul** poate fi apelat de mai multe ori pe **aceeași resursă**.</​note>​+Iar output-ul arată ca mai jos. 
 + 
 +<​file>​ 
 +Constructor A 
 +Constructor B 
 +Constructor A 
 +Constructor C 
 +Constructor D 
 + 
 +Destructor D 
 +Destructor C 
 +Destructor A 
 +Destructor B 
 +Destructor A 
 +</​file>​ 
 + 
 +<note warning>​Comportamentul descris mai sus apare din cauza **problemei rombului**, care generează o **ambiguitate** ce conduce la **dublul apel** al constructorului și al destructorului clasei de bază **A**. Această situație poate deveni problematică în special în scenariile în care superclasa **A** gestionează resurse **alocate dinamic**. În astfel de cazuri, **ambiguitatea** poate duce la **comportament nedefinit**, cum ar fi **memory leaks** sau chiar **crash-uri** ale aplicației,​ deoarece **destructorul** poate fi apelat de mai multe ori pe **aceeași resursă**.</​note>​
  
 Rezolvarea acestei probleme este **derivarea virtuală** a claselor intermediare **B** și respectiv **C** după cum urmează. Rezolvarea acestei probleme este **derivarea virtuală** a claselor intermediare **B** și respectiv **C** după cum urmează.
Line 242: Line 258:
 Deși ordinea apelării constructorilor este cea firească în cazul destructorilor putem observa că aceștia **nu** se apelează în **ordinea inversă** constructorilor,​ ceea ce înseamnă că la **dezalocarea memoriei** pentru pointerul **obj** nu se produce o **legătură întârziată (late binding)**. Deși ordinea apelării constructorilor este cea firească în cazul destructorilor putem observa că aceștia **nu** se apelează în **ordinea inversă** constructorilor,​ ceea ce înseamnă că la **dezalocarea memoriei** pentru pointerul **obj** nu se produce o **legătură întârziată (late binding)**.
  
-<note warning>​În cazul **problemei rombului** clasa **A** nu este o **clasă abstractă** sau o **interfață**. Toate clasele existente sunt **clase reale**, adică sunt **instanțiabile**,​ deci asigurarea **legăturii întârziate** se poate face **doar** prin intermediul **metodelor virtuale**.</​note>​+<note warning>​În cazul **problemei rombului** ​prezentate în acest laborator ​clasa **A** nu este o **clasă abstractă** sau o **interfață**. Toate clasele existente sunt **clase reale**, adică sunt **instanțiabile**,​ deci asigurarea **legăturii întârziate** se poate face **doar** prin intermediul **metodelor virtuale**.</​note>​
  
-Soluția este să marcăm destructorul clasei **A** ca fiind **virtual**,​ astfel **tabela virtuală de pointeri** va fi moștenită de clasele **B**, **C****D**.+Soluția este să marcăm destructorul clasei **A** ca fiind **virtual**,​ astfel **tabela virtuală de pointeri** va fi moștenită de clasele **B**, **C** și respectiv ​**D**.
  
 <code cpp> <code cpp>
Line 276: Line 292:
 Destructor A Destructor A
 </​file>​ </​file>​
 +
 +<note tip>​Trebuie menționat însă faptul că limbajul C++ **permite** organizarea în formă de **romb** și pentru **clasele abstracte** și respectiv **interfețe**. Spre exemplu putem avea patru **clase abstracte** organizate în formă de **romb** iar **clasa de la baza rombului (clasa nepot)** este moștenită de o **clasă instanțiabilă**.</​note>​
  
 ==== ==== ==== ====
poo-is-ab/laboratoare/12.1734418931.txt.gz · Last modified: 2024/12/17 09:02 by razvan.cristea0106
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0