Differences

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

Link to this comparison view

poo-is-ab:laboratoare:09 [2025/11/23 14:43]
razvan.cristea0106 [Interfețe]
poo-is-ab:laboratoare:09 [2025/12/09 11:26] (current)
razvan.cristea0106 [Metode virtuale]
Line 19: Line 19:
 De exemplu, dacă avem o funcție **''​adunare''​** supraîncărcată pentru a lucra cu numere întregi și cu numere reale, **compilatorul** determină **automat** care versiune a funcției urmează să fie apelată, în funcție de **tipul** datelor primite ca argumente. Avantajul acestui tip de polimorfism este **viteza de execuție**,​ deoarece decizia a fost deja luată **înainte** ca programul să ruleze. De exemplu, dacă avem o funcție **''​adunare''​** supraîncărcată pentru a lucra cu numere întregi și cu numere reale, **compilatorul** determină **automat** care versiune a funcției urmează să fie apelată, în funcție de **tipul** datelor primite ca argumente. Avantajul acestui tip de polimorfism este **viteza de execuție**,​ deoarece decizia a fost deja luată **înainte** ca programul să ruleze.
  
-Cu toate acestea, există cazuri în care decizia pentru ​funcția/metoda ce trebuie apelată **nu** poate fi luată de către compilator, ci doar în timpul execuției. Acest procedeu este cunoscut sub denumirea de **polimorfism întârziat (late binding sau run-time polymorphism)**. Acest concept este strâns legat de **suprascrierea funcțiilor (overriding)** și de utilizarea mecanismelor de **moștenire** și **metode virtuale** în C++.+Cu toate acestea, există cazuri în care decizia pentru metoda ce trebuie apelată **nu** poate fi luată de către compilator, ci doar în timpul execuției. Acest procedeu este cunoscut sub denumirea de **polimorfism întârziat (late binding sau run-time polymorphism)**. Acest concept este strâns legat de **suprascrierea funcțiilor (overriding)** și de utilizarea mecanismelor de **moștenire** și **metode virtuale** în C++.
  
 ==== Overloading vs Overriding ==== ==== Overloading vs Overriding ====
Line 28: Line 28:
 | Se aplică funcțiilor/​metodelor din **aceeași clasă, același namespace, sau același fișier** ​      | Apare în ierarhiile de clase (**moștenire**) ​           | | Se aplică funcțiilor/​metodelor din **aceeași clasă, același namespace, sau același fișier** ​      | Apare în ierarhiile de clase (**moștenire**) ​           |
 | Funcțiile/​metodele au **același nume**, dar **diferă** prin **numărul, tipul sau ordinea parametrilor** | O metodă dintr-o clasă derivată **suprascrie** comportamentul unei **metode virtuale** din clasa de bază | | Funcțiile/​metodele au **același nume**, dar **diferă** prin **numărul, tipul sau ordinea parametrilor** | O metodă dintr-o clasă derivată **suprascrie** comportamentul unei **metode virtuale** din clasa de bază |
-| Alegerea funcției/​metodei este făcută de către **compilator** pe baza semnăturii acesteia | Alegerea metodei care va fi apelată este făcută la **momentul execuției**, în funcție de **tipul dinamic** al obiectului | +| Alegerea funcției/​metodei este făcută de către **compilator** pe baza semnăturii acesteia | Alegerea metodei care va fi apelată este făcută la **runtime**, în funcție de **tipul dinamic** al obiectului | 
-| **Nu** necesită metode virtuale/​virtual pure                              | **Necesită** utilizarea metodelor virtuale/​virtual pure în clasa de bază|+| **Nu** necesită metode virtuale/​virtual pure                               | **Necesită** utilizarea metodelor virtuale/​virtual pure în clasa de bază |
 | Este o formă de polimorfism timpuriu (**early binding**) ​   | Este o formă de polimorfism întârziat (**late binding**) ​ | | Este o formă de polimorfism timpuriu (**early binding**) ​   | Este o formă de polimorfism întârziat (**late binding**) ​ |
 | Are un impact **redus** asupra performanței,​ deoarece decizia se ia la compilare | Are un impact **ușor mai mare** asupra performanței,​ deoarece decizia se ia în timpul execuției | | Are un impact **redus** asupra performanței,​ deoarece decizia se ia la compilare | Are un impact **ușor mai mare** asupra performanței,​ deoarece decizia se ia în timpul execuției |
Line 51: Line 51:
 **Object slicing** reprezintă situația în care, la copierea unui obiect **derivat** într-o variabilă de **tipul clasei de bază**, se păstrează doar **partea de bază** a obiectului, iar atributele și comportamentele specifice **clasei derivate** sunt **„tăiate” (eliminate)**,​ obiectul comportându-se ca unul de **tipul clasei de bază**.</​note>​ **Object slicing** reprezintă situația în care, la copierea unui obiect **derivat** într-o variabilă de **tipul clasei de bază**, se păstrează doar **partea de bază** a obiectului, iar atributele și comportamentele specifice **clasei derivate** sunt **„tăiate” (eliminate)**,​ obiectul comportându-se ca unul de **tipul clasei de bază**.</​note>​
  
-<​note>​În C++ există ​**două** tipuri de metode virtuale ​și anume: ​**metode virtuale** ș**metode ​virtual ​pure**. Diferența între cele două tipuri constă în faptul ​că o metodă virtual pură **nu** are implementare ​în **clasa de bază**.</​note>​+Pentru a putea înțelege mai bine cum se poate realiza ​**legătura întârziată (late binding)** și cum apare fenomenul de **Object Slicing** vom propune un exemplu simplu de cod. Pentru a putea declara o metodă virtuală în C++ se folosește cuvântul cheie **virtual** ​care anunță compilatorul ​că metoda poate fi **suprascrisă** în clasele derivate și că aceasta trebuie să fie gestionată prin intermediul ​**vtable**.
  
-În limbajul ​C++ pentru a declara o funcție virtuală într-o clasă se utilizeaza cuvântul cheie **virtual**. ​Dacă am spus funcție virtuală asta înseamnă că în clasa de bază acea funcție va avea implementareCa și exemplu ​vom propune ​clasele **Animal** și **Caine**.+<code cpp> 
 +#include <​iostream>​ 
 + 
 +class Baza 
 +
 +public: 
 + 
 +    virtual void afisare() const // metoda virtuala 
 +    { 
 +        std::cout << "Sunt un obiect de tipul clasei Baza\n";​ 
 +    } 
 +}; 
 + 
 +class Derivata : public Baza 
 +
 +public: 
 + 
 +    void afisare() const // aceasta functie membra suprascrie comportamentul metodei afisare din clasa parinte 
 +    { 
 +        std::cout << "Sunt un obiect de tipul clasei Derivata\n";​ 
 +    } 
 +}; 
 + 
 +int main() 
 +
 +    Derivata obj; 
 + 
 +    // 1. FARA slicing — prin pointer 
 + 
 +    Baza* ptr = &obj; 
 +    ptr->​afisare();​ // se apeleaza metoda din clasa Derivata 
 + 
 +    // 2. FARA slicing — prin referinta 
 + 
 +    Baza& ref = obj; 
 +    ref.afisare();​ // se apeleaza metoda din clasa Derivata 
 + 
 +    // 3. CU slicing — prin copiere (valoare) 
 + 
 +    Baza b = obj; // aici se produce fenomenul de Object Slicing 
 +    b.afisare();​ // se apeleaza metoda din Baza (partea din clasa Derivata este "​taiata"​) 
 + 
 +    return 0; 
 +
 +</​code>​ 
 + 
 +<​note>​În C++ există **două** tipuri de metode virtuale și anume: **metode virtuale** și **metode ​virtual ​pure**. Diferența între cele două tipuri constă în faptul ​că unei metode virtual pure **îi poate lipsi** implementarea ​în **clasa de bază**.</​note>​ 
 + 
 +În continuare propunem ca și exemplu ​practic ​clasele **Animal** și **Caine**, unde ne dorim să punem în evidență conceputul de **late binding** și să adăugăm informații noi cu privire la acestă noțiune nouă pe care o învățăm.
  
 <code cpp> <code cpp>
Line 85: Line 133:
 </​code>​ </​code>​
  
-În funcția **main** vom demostra faptul că deși câinele este un animal se vor apela metodele specifice tipurilor de date din cauza faptului că în clasa Animal metoda **''​afisare''​** nu este declarată ca fiind virtuală.+În funcția **main** vom demostra faptul că deși câinele este un animal, totuși vom observa că se vor apela metodele specifice tipurilor de date din cauza faptului că în clasa Animal metoda **''​afisare''​** nu este declarată ca fiind virtuală.
  
 <code cpp> <code cpp>
Line 167: Line 215:
 </​code>​ </​code>​
  
-<note important>​Cuvântul cheie **override** în **C++** este folosit pentru a specifica în mod **explicit** că o funcție membră dintr-o **clasă derivată** suprascrie o metodă ​**virtuală** din **clasa de bază**. Acest mecanism oferă mai multă siguranță în ceea ce privește **suprascrierea** metodelor și ajută la prevenirea **erorilor de programare**.</​note>​+<note important>​Cuvântul cheie **override** în **C++** este folosit pentru a specifica în mod **explicit** că o funcție membră dintr-o **clasă derivată** suprascrie o **metodă ​virtuală** din **clasa de bază**. Acest mecanism oferă mai multă siguranță în ceea ce privește **suprascrierea** metodelor și ajută la prevenirea **erorilor de programare**.</​note>​
  
 ==== Clase abstracte ==== ==== Clase abstracte ====
  
-În limbajul C++, o **clasă abstractă** este o clasă care conține **cel puțin** o **metodă virtuală pură**. **Metoda virtuală pură** este o funcție declarată în clasa de bază, dar care **nu are o implementare** în această clasă, **obligând** astfel **clasele derivate** să o **suprascrie**. O **clasă abstractă** este utilizată pentru a defini un comportament **general** care trebuie să fie specificat în **mod detaliat** în **clasele derivate**.+În limbajul C++, o **clasă abstractă** este o clasă care conține **cel puțin** o **metodă virtuală pură**. **Metoda virtuală pură** este o funcție ​membră ​declarată în clasa de bază, dar care **nu are neapărat ​o implementare** în această clasă, **obligând** astfel **clasele derivate** să o **suprascrie**. O **clasă abstractă** este utilizată pentru a defini un comportament **general** care trebuie să fie specificat în **mod detaliat** în **clasele derivate**.
  
-<note warning>​O clasă abstractă **nu** poate fi folosită pentru a crea **obiecte**. Este concepută să fie doar o bază pentru alte clase care o vor moșteni. În schimb se pot instanția **pointeri** de tipul acestei clase care să fie inițializati cu ajutorul **claselor derivate**. Un alt aspect ce trebuie menționat este faptul că **orice** clasă derivată dintr-o clasă abstractă **trebuie** să implementeze **toate** metodele virtual pure, altfel va deveni ea însăși o **clasă abstractă**.</​note>​+<note warning>​O clasă abstractă **nu** poate fi folosită pentru a crea **obiecte**. Este concepută să fie doar o bază pentru alte clase care o vor **moșteni**. În schimb se pot instanția **pointeri** de tipul acestei clase care să fie inițializati cu ajutorul **claselor derivate**. Un alt aspect ce trebuie menționat este faptul că **orice** clasă derivată dintr-o clasă abstractă **trebuie** să implementeze **toate** metodele virtual pure, altfel va deveni ea însăși o **clasă abstractă**.</​note>​
  
 O clasă abstractă poate avea membri și metode precum constructori,​ getteri, setteri și destructor care vor fi apelate în clasele derivate. În continuare vom prezenta modul în care putem pune în evidență conceptul de **late binding** transformând clasa **Animal** într-o clasă abstractă. O clasă abstractă poate avea membri și metode precum constructori,​ getteri, setteri și destructor care vor fi apelate în clasele derivate. În continuare vom prezenta modul în care putem pune în evidență conceptul de **late binding** transformând clasa **Animal** într-o clasă abstractă.
Line 323: Line 371:
 | **Membri de date** ​         | Nu poate avea membri ​      | Poate avea membri ​           | | **Membri de date** ​         | Nu poate avea membri ​      | Poate avea membri ​           |
 | **Constructori** ​           | Nu poate avea constructori ​        | Poate avea constructori ​             | | **Constructori** ​           | Nu poate avea constructori ​        | Poate avea constructori ​             |
-| **Moștenire multiplă** ​     | Este utilizată pentru moștenirea multiplă, mai ales pentru a defini contracte comune | Este utilizată în ierarhii ​simple sau complexe, dar poate genera ambiguități în moștenirea multiplă |+| **Moștenire multiplă** ​     | Este utilizată pentru moștenirea multiplă, mai ales pentru a defini contracte comune | Este utilizată în ierarhii ​de clase, dar poate genera ambiguități în moștenirea multiplă |
 | **Scop** ​                   | Definește un contract strict pentru clasele derivate | Definește un comportament parțial și oferă reutilizarea codului | | **Scop** ​                   | Definește un contract strict pentru clasele derivate | Definește un comportament parțial și oferă reutilizarea codului |
 | **Destructor** ​             | Destructorul virtual pur este obligatoriu atunci când în clasele derivate există membri de tip pointer alocați dinamic | Destructorul virtual trebuie implementat atunci când există pointeri alocați dinamic în clasele derivate | | **Destructor** ​             | Destructorul virtual pur este obligatoriu atunci când în clasele derivate există membri de tip pointer alocați dinamic | Destructorul virtual trebuie implementat atunci când există pointeri alocați dinamic în clasele derivate |
poo-is-ab/laboratoare/09.1763901839.txt.gz · Last modified: 2025/11/23 14:43 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