Differences

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

Link to this comparison view

poo-is-ab:laboratoare:10 [2025/12/01 13:40]
razvan.cristea0106 [Supraîncărcarea operatorului << pentru o clasă abstractă]
poo-is-ab:laboratoare:10 [2025/12/04 09:00] (current)
razvan.cristea0106 [Vector de obiecte neomogene]
Line 46: Line 46:
 }; };
 </​code>​ </​code>​
 +
 +<​note>​Așa cum am discutat în cadrul laboratorului anterior, atunci când declarăm o metodă ca fiind **virtual pură**, clasa care o conține devine automat o **clasă abstractă**. Totuși, faptul că o **funcție membră** este marcată drept virtual pură **nu ne împiedică deloc** să îi oferim o implementare în clasa unde a fost declarată. Această marcare, exprimată prin sintaxa **''​= 0''​**,​ are rolul de a face clasa **neinstanțiabilă**,​ **nu de a interzice existența unei definiții**. Cu alte cuvinte, putem avea în continuare un **comportament de bază** pentru metoda respectivă,​ chiar dacă **obligăm subclasele** să o **suprascrie**.</​note>​
 +
 +În cele ce urmează vom exemplifica printr-o secvență de cod ceea ce am menționat anterior.
 +
 +<code cpp>
 +#include <​iostream>​
 +
 +class A
 +{
 +public:
 +
 +    // Metoda este marcata ca fiind virtual pura -> clasa devine abstracta
 +    // Totusi ii putem oferi o implementare
 +    virtual void f() = 0;
 +};
 +
 +// Implementarea metodei virtual pure trebuie sa fie in afara clasei,
 +// deoarece limbajul C++ nu permite definirea unei metode virtual pure direct in interiorul clasei
 + void A::f()
 +{
 +    std::cout << "​Comportament default din A::​f()\n";​
 +}
 +
 +class B : public A
 +{
 +public:
 +
 +    // B suprascrie metoda f si foloseste implementarea din clasa de baza
 +    void f() override
 +    {
 +        std::cout << "​B::​f() - inainte de apelul bazei\n";​
 +        A::f(); // se apeleaza metoda superclasei
 +        std::cout << "​B::​f() - dupa apelul bazei\n";​
 +    }
 +};
 +
 +class C : public A
 +{
 +public:
 +
 +    // C suprascrie metoda f si inlocuieste complet comportamentul
 +    void f() override
 +    {
 +        std::cout << "​C::​f() - comportament complet redefinit\n";​
 +    }
 +};
 +
 +int main()
 +{
 +    // A a; // eroare de compilare, clasa nu este instantiabila
 +    // A* ptr = new A(); // nu se poate, clasa nu este instantiabila
 +
 +    A* p1 = new B();
 +    A* p2 = new C();
 +
 +    std::cout << "--- Apel prin B ---\n";​
 +    p1->f();
 +
 +    std::cout << "\n--- Apel prin C ---\n";​
 +    p2->f();
 +
 +    delete p1;
 +    delete p2;
 +
 +    return 0;
 +}
 +</​code>​
 +
 +În continuare propunem un tabel în care se prezintă caracteristicile metodelor virtuale și respectiv virtual pure pentru a rezuma explicațiile oferite mai sus.
 +
 +^               ​Caracteristică ​                   ^      Metodă virtuală ​     ^            Metodă virtuală pură             ^
 +| Obligă clasa derivată să o suprascrie? ​         |            Nu             ​| ​                    ​Da ​                     |
 +| Clasa devine abstractă? ​                        ​| ​           Nu             ​| ​                    ​Da ​                     |
 +| Are implementare în clasa de bază? ​             |     Da (obligatoriu) ​     |                Nu neapărat ​                 |
 +| Poate fi apelată din subclasă? ​                 |            Da             ​| ​                    ​Da ​                     |
 +| Sintaxă ​                                        ​| ​ ''​virtual void f();'' ​   |          ''​virtual void f() = 0;'' ​         |
 +| Permite instanțierea clasei de bază? ​           |            Da             ​| ​                    ​Nu ​                     |
 +| Apelabilă prin pointer la tipul bazei? ​         |            Da             ​| ​                    ​Da ​                     |
  
 <note important>​În C++, unui **destructor virtual pur** trebuie să îi oferim o **implementare** deoarece va fi **întotdeauna apelat** atunci când un **obiect derivat** este **distrus**. Această cerință se bazează pe mecanismul de distrugere a obiectelor, care implică apelarea destructorilor **în ordine inversă** a **constructorilor**,​ inclusiv pentru clasa de bază.</​note>​ <note important>​În C++, unui **destructor virtual pur** trebuie să îi oferim o **implementare** deoarece va fi **întotdeauna apelat** atunci când un **obiect derivat** este **distrus**. Această cerință se bazează pe mecanismul de distrugere a obiectelor, care implică apelarea destructorilor **în ordine inversă** a **constructorilor**,​ inclusiv pentru clasa de bază.</​note>​
  
-Prin urmare vom furniza o implementare pentru destructorul ​clasei **ProdusElectronic** ​după cum urmează în secțiunea de cod de mai jos.+Odată înțelese conceptele privind metodele virtuale și virtual pure, putem oferi implementarea destructorului ​clasei **ProdusElectronic**, așa cum este ilustrată în codul următor.
  
 <code cpp> <code cpp>
Line 94: Line 173:
 </​code>​ </​code>​
  
-Iar implementările metodelor celor două clase se pot observa în blocurile de mai jos.+Iar implementările metodelor celor două clase se pot observa în blocurile ​de cod de mai jos.
  
 <code cpp> <code cpp>
poo-is-ab/laboratoare/10.1764589256.txt.gz · Last modified: 2025/12/01 13:40 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