This shows you the differences between two versions of the page.
|
poo-is-ab:laboratoare:10 [2025/09/23 23:06] razvan.cristea0106 [Introducere] |
poo-is-ab:laboratoare:10 [2025/12/01 13:40] (current) razvan.cristea0106 [Supraîncărcarea operatorului << pentru o clasă abstractă] |
||
|---|---|---|---|
| Line 40: | Line 40: | ||
| public: | public: | ||
| - | virtual ~ProdusElectronic() = 0; // destructor virtual pur | + | virtual ~ProdusElectronic() = 0; // destructor virtual pur |
| - | virtual float getPret() const = 0; | + | virtual float getPret() const = 0; |
| - | virtual char* getProducator() const = 0; | + | virtual char* getProducator() const = 0; |
| }; | }; | ||
| </code> | </code> | ||
| Line 54: | Line 54: | ||
| ProdusElectronic::~ProdusElectronic() | ProdusElectronic::~ProdusElectronic() | ||
| { | { | ||
| - | // chiar daca nu scriem nimic este necesar sa existe pentru a putea functiona corect dezalocarea memoriei | + | // chiar daca nu scriem nimic este necesar sa existe pentru a putea functiona corect dezalocarea memoriei |
| } | } | ||
| </code> | </code> | ||
| Line 63: | Line 63: | ||
| class Laptop : public ProdusElectronic | class Laptop : public ProdusElectronic | ||
| { | { | ||
| - | float pret; | + | float pret; |
| - | char* producator; | + | char* producator; |
| public: | public: | ||
| - | Laptop(); | + | Laptop(); |
| - | Laptop(const float& pret, const char* producator); | + | Laptop(const float& pret, const char* producator); |
| - | ~Laptop(); | + | ~Laptop(); |
| - | float getPret() const override; | + | float getPret() const override; |
| - | char* getProducator() const override; | + | char* getProducator() const override; |
| }; | }; | ||
| </code> | </code> | ||
| Line 80: | Line 80: | ||
| class SmartPhone : public ProdusElectronic | class SmartPhone : public ProdusElectronic | ||
| { | { | ||
| - | float pret; | + | float pret; |
| - | char* producator; | + | char* producator; |
| public: | public: | ||
| - | SmartPhone(); | + | SmartPhone(); |
| - | SmartPhone(const float& pret, const char* producator); | + | SmartPhone(const float& pret, const char* producator); |
| - | ~SmartPhone(); | + | ~SmartPhone(); |
| - | float getPret() const override; | + | float getPret() const override; |
| - | char* getProducator() const override; | + | char* getProducator() const override; |
| }; | }; | ||
| </code> | </code> | ||
| Line 99: | Line 99: | ||
| Laptop::Laptop() | Laptop::Laptop() | ||
| { | { | ||
| - | pret = 0.0f; | + | pret = 0.0f; |
| - | producator = nullptr; | + | producator = nullptr; |
| } | } | ||
| Laptop::Laptop(const float& pret, const char* producator) | Laptop::Laptop(const float& pret, const char* producator) | ||
| { | { | ||
| - | this->pret = pret; | + | this->pret = pret; |
| - | if (producator != nullptr) | + | if (producator != nullptr) |
| - | { | + | { |
| - | this->producator = new char[strlen(producator) + 1]; | + | this->producator = new char[strlen(producator) + 1]; |
| - | strcpy(this->producator, producator); | + | strcpy(this->producator, producator); |
| - | } | + | } |
| - | else | + | else |
| - | { | + | { |
| - | this->producator = nullptr; | + | this->producator = nullptr; |
| - | } | + | } |
| } | } | ||
| Laptop::~Laptop() | Laptop::~Laptop() | ||
| { | { | ||
| - | if (producator != nullptr) | + | if (producator != nullptr) |
| - | { | + | { |
| - | delete[] producator; | + | delete[] producator; |
| - | } | + | } |
| } | } | ||
| float Laptop::getPret() const | float Laptop::getPret() const | ||
| { | { | ||
| - | return pret; | + | return pret; |
| } | } | ||
| char* Laptop::getProducator() const | char* Laptop::getProducator() const | ||
| { | { | ||
| - | return producator; | + | return producator; |
| } | } | ||
| </code> | </code> | ||
| Line 140: | Line 140: | ||
| SmartPhone::SmartPhone() | SmartPhone::SmartPhone() | ||
| { | { | ||
| - | pret = 0.0f; | + | pret = 0.0f; |
| - | producator = nullptr; | + | producator = nullptr; |
| } | } | ||
| SmartPhone::SmartPhone(const float& pret, const char* producator) | SmartPhone::SmartPhone(const float& pret, const char* producator) | ||
| { | { | ||
| - | this->pret = pret; | + | this->pret = pret; |
| - | if (producator != nullptr) | + | if (producator != nullptr) |
| - | { | + | { |
| - | this->producator = new char[strlen(producator) + 1]; | + | this->producator = new char[strlen(producator) + 1]; |
| - | strcpy(this->producator, producator); | + | strcpy(this->producator, producator); |
| - | } | + | } |
| - | else | + | else |
| - | { | + | { |
| - | this->producator = nullptr; | + | this->producator = nullptr; |
| - | } | + | } |
| } | } | ||
| SmartPhone::~SmartPhone() | SmartPhone::~SmartPhone() | ||
| { | { | ||
| - | if (producator != nullptr) | + | if (producator != nullptr) |
| - | { | + | { |
| - | delete[] producator; | + | delete[] producator; |
| - | } | + | } |
| } | } | ||
| float SmartPhone::getPret() const | float SmartPhone::getPret() const | ||
| { | { | ||
| - | return pret; | + | return pret; |
| } | } | ||
| char* SmartPhone::getProducator() const | char* SmartPhone::getProducator() const | ||
| { | { | ||
| - | return producator; | + | return producator; |
| } | } | ||
| </code> | </code> | ||
| Line 186: | Line 186: | ||
| int main() | int main() | ||
| { | { | ||
| - | int nrProduse = 5; | + | int nrProduse = 5; |
| - | ProdusElectronic** produse = new ProdusElectronic * [nrProduse]; // vector de obiecte neomogene | + | ProdusElectronic** produse = new ProdusElectronic * [nrProduse]; // vector de obiecte neomogene |
| - | produse[0] = new Laptop(5499.99f, "HP"); // late binding | + | produse[0] = new Laptop(5499.99f, "HP"); // late binding |
| - | produse[1] = new SmartPhone(2499.99f, "Motorola"); | + | produse[1] = new SmartPhone(2499.99f, "Motorola"); |
| - | produse[2] = new Laptop(3000.0f, "Asus"); | + | produse[2] = new Laptop(3000.0f, "Asus"); |
| - | produse[3] = new Laptop(7999.99f, "Lenovo"); | + | produse[3] = new Laptop(7999.99f, "Lenovo"); |
| - | produse[4] = new SmartPhone(3999.99f, "Apple"); | + | produse[4] = new SmartPhone(3999.99f, "Apple"); |
| - | for (int i = 0; i < nrProduse; i++) | + | for (int i = 0; i < nrProduse; i++) |
| - | { | + | { |
| - | std::cout << "Pretul produsului este: " << produse[i]->getPret() << '\n'; | + | std::cout << "Pretul produsului este: " << produse[i]->getPret() << '\n'; |
| - | std::cout << "Numele producatorului este: " << produse[i]->getProducator() << "\n\n"; | + | std::cout << "Numele producatorului este: " << produse[i]->getProducator() << "\n\n"; |
| - | } | + | } |
| - | return 0; | + | return 0; |
| } | } | ||
| </code> | </code> | ||
| Line 213: | Line 213: | ||
| int main() | int main() | ||
| { | { | ||
| - | int nrProduse = 5; | + | int nrProduse = 5; |
| - | ProdusElectronic** produse = new ProdusElectronic * [nrProduse]; | + | ProdusElectronic** produse = new ProdusElectronic * [nrProduse]; |
| - | produse[0] = new Laptop(5499.99f, "HP"); // late binding | + | produse[0] = new Laptop(5499.99f, "HP"); // late binding |
| - | produse[1] = new SmartPhone(2499.99f, "Motorola"); | + | produse[1] = new SmartPhone(2499.99f, "Motorola"); |
| - | produse[2] = new Laptop(3000.0f, "Asus"); | + | produse[2] = new Laptop(3000.0f, "Asus"); |
| - | produse[3] = new Laptop(7999.99f, "Lenovo"); | + | produse[3] = new Laptop(7999.99f, "Lenovo"); |
| - | produse[4] = new SmartPhone(3999.99f, "Apple"); | + | produse[4] = new SmartPhone(3999.99f, "Apple"); |
| - | for (int i = 0; i < nrProduse; i++) | + | for (int i = 0; i < nrProduse; i++) |
| - | { | + | { |
| - | std::cout << "Pretul produsului este: " << produse[i]->getPret() << '\n'; | + | std::cout << "Pretul produsului este: " << produse[i]->getPret() << '\n'; |
| - | std::cout << "Numele producatorului este: " << produse[i]->getProducator() << "\n\n"; | + | std::cout << "Numele producatorului este: " << produse[i]->getProducator() << "\n\n"; |
| - | } | + | } |
| - | for (int i = 0; i < nrProduse; i++) | + | for (int i = 0; i < nrProduse; i++) |
| - | { | + | { |
| - | delete produse[i]; // eliberam fiecare slot din vector | + | delete produse[i]; // eliberam fiecare slot din vector |
| - | } | + | } |
| - | delete[] produse; // stergem vectorul | + | delete[] produse; // stergem vectorul |
| - | return 0; | + | return 0; |
| } | } | ||
| </code> | </code> | ||
| Line 247: | Line 247: | ||
| În contextul exemplului prezentat anterior, ar fi foarte elegant să putem afișa elementele vectorului folosind **operatorul %%<<%%**, ceea ce ar simplifica și uniformiza procesul de afișare. Totuși, o problemă fundamentală apare din faptul că acest operator poate fi **supraîncărcat**, dar nu și **suprascris**. | În contextul exemplului prezentat anterior, ar fi foarte elegant să putem afișa elementele vectorului folosind **operatorul %%<<%%**, ceea ce ar simplifica și uniformiza procesul de afișare. Totuși, o problemă fundamentală apare din faptul că acest operator poate fi **supraîncărcat**, dar nu și **suprascris**. | ||
| - | Prin urmare **operatorul %%<<%%** nu poate fi declarat **virtual**, astfel încât să permită apelul unei implementări specifice **clasei derivate** atunci când este utilizat printr-un **pointer** sau o **referință** la **clasa de bază**. Soluția implică de obicei definirea unei metode virtuale în **clasa abstractă** și utilizarea acesteia în supraîncărcarea **operatorului %%<<%%**. | + | Prin urmare **operatorul %%<<%%** nu poate fi declarat **virtual**, astfel încât să permită apelul unei implementări specifice **clasei derivate** atunci când este utilizat printr-un **pointer** sau o **referință** la **clasa de bază**. Soluția implică de obicei definirea unei metode virtuale în **clasa abstractă** și utilizarea acesteia în supraîncărcarea **operatorului de afișare %%<<%%**. |
| Această abordare oferă o separare clară între logica specifică de afișare și mecanismul **operatorului %%<<%%**, respectând în același timp principiile polimorfismului. | Această abordare oferă o separare clară între logica specifică de afișare și mecanismul **operatorului %%<<%%**, respectând în același timp principiile polimorfismului. | ||
| Line 258: | Line 258: | ||
| protected: | protected: | ||
| - | virtual void afisare(std::ostream& out) const = 0; // va fi folosita pentru operatorul << | + | virtual void afisare(std::ostream& out) const = 0; // va fi folosita pentru operatorul << |
| public: | public: | ||
| - | virtual ~ProdusElectronic() = 0; | + | virtual ~ProdusElectronic() = 0; |
| - | virtual float getPret() const = 0; | + | virtual float getPret() const = 0; |
| - | virtual char* getProducator() const = 0; | + | virtual char* getProducator() const = 0; |
| - | friend std::ostream& operator<<(std::ostream& out, const ProdusElectronic* const& produsElectronic); | + | friend std::ostream& operator<<(std::ostream& out, const ProdusElectronic* const& produsElectronic); |
| }; | }; | ||
| </code> | </code> | ||
| Line 276: | Line 276: | ||
| std::ostream& operator<<(std::ostream& out, const ProdusElectronic* const& produsElectronic) | std::ostream& operator<<(std::ostream& out, const ProdusElectronic* const& produsElectronic) | ||
| { | { | ||
| - | produsElectronic->afisare(out); // ne folosim de late binding | + | produsElectronic->afisare(out); // ne folosim de late binding |
| - | return out; | + | return out; |
| } | } | ||
| </code> | </code> | ||
| Line 286: | Line 286: | ||
| class Laptop : public ProdusElectronic | class Laptop : public ProdusElectronic | ||
| { | { | ||
| - | float pret; | + | float pret; |
| - | char* producator; | + | char* producator; |
| protected: | protected: | ||
| - | void afisare(std::ostream& out) const override; | + | void afisare(std::ostream& out) const override; |
| public: | public: | ||
| - | Laptop(); | + | Laptop(); |
| - | Laptop(const float& pret, const char* producator); | + | Laptop(const float& pret, const char* producator); |
| - | ~Laptop(); | + | ~Laptop(); |
| - | float getPret() const override; | + | float getPret() const override; |
| - | char* getProducator() const override; | + | char* getProducator() const override; |
| }; | }; | ||
| </code> | </code> | ||
| Line 307: | Line 307: | ||
| class SmartPhone : public ProdusElectronic | class SmartPhone : public ProdusElectronic | ||
| { | { | ||
| - | float pret; | + | float pret; |
| - | char* producator; | + | char* producator; |
| protected: | protected: | ||
| - | void afisare(std::ostream& out) const override; | + | void afisare(std::ostream& out) const override; |
| public: | public: | ||
| - | SmartPhone(); | + | SmartPhone(); |
| - | SmartPhone(const float& pret, const char* producator); | + | SmartPhone(const float& pret, const char* producator); |
| - | ~SmartPhone(); | + | ~SmartPhone(); |
| - | float getPret() const override; | + | float getPret() const override; |
| - | char* getProducator() const override; | + | char* getProducator() const override; |
| }; | }; | ||
| </code> | </code> | ||
| Line 330: | Line 330: | ||
| void Laptop::afisare(std::ostream& out) const | void Laptop::afisare(std::ostream& out) const | ||
| { | { | ||
| - | out << "Pretul laptopului este: " << pret << '\n'; | + | out << "Pretul laptopului este: " << pret << '\n'; |
| - | out << "Numele producatorului de laptopuri este: "; | + | out << "Numele producatorului de laptopuri este: "; |
| - | if (producator != nullptr) | + | if (producator != nullptr) |
| - | { | + | { |
| - | out << producator << '\n'; | + | out << producator << '\n'; |
| - | } | + | } |
| - | else | + | else |
| - | { | + | { |
| - | out << "N/A\n"; | + | out << "N/A\n"; |
| - | } | + | } |
| } | } | ||
| </code> | </code> | ||
| Line 347: | Line 347: | ||
| void SmartPhone::afisare(std::ostream& out) const | void SmartPhone::afisare(std::ostream& out) const | ||
| { | { | ||
| - | out << "Pretul smartphone-ului este: " << pret << '\n'; | + | out << "Pretul smartphone-ului este: " << pret << '\n'; |
| - | out << "Numele producatorului de smartphone-uri este: "; | + | out << "Numele producatorului de smartphone-uri este: "; |
| - | if (producator != nullptr) | + | if (producator != nullptr) |
| - | { | + | { |
| - | out << producator << '\n'; | + | out << producator << '\n'; |
| - | } | + | } |
| - | else | + | else |
| - | { | + | { |
| - | out << "N/A\n"; | + | out << "N/A\n"; |
| - | } | + | } |
| } | } | ||
| </code> | </code> | ||
| Line 369: | Line 369: | ||
| int main() | int main() | ||
| { | { | ||
| - | int nrProduse = 5; | + | int nrProduse = 5; |
| - | ProdusElectronic** produse = new ProdusElectronic * [nrProduse]; | + | ProdusElectronic** produse = new ProdusElectronic * [nrProduse]; |
| - | produse[0] = new Laptop(5499.99f, "HP"); | + | produse[0] = new Laptop(5499.99f, "HP"); |
| - | produse[1] = new SmartPhone(2499.99f, "Motorola"); | + | produse[1] = new SmartPhone(2499.99f, "Motorola"); |
| - | produse[2] = new Laptop(3000.0f, "Asus"); | + | produse[2] = new Laptop(3000.0f, "Asus"); |
| - | produse[3] = new Laptop(7999.99f, "Lenovo"); | + | produse[3] = new Laptop(7999.99f, "Lenovo"); |
| - | produse[4] = new SmartPhone(3999.99f, "Apple"); | + | produse[4] = new SmartPhone(3999.99f, "Apple"); |
| - | for (int i = 0; i < nrProduse; i++) | + | for (int i = 0; i < nrProduse; i++) |
| - | { | + | { |
| - | std::cout << produse[i] << '\n'; // se foloseste operatorul << definit in interfata ProdusElectronic | + | std::cout << produse[i] << '\n'; // se foloseste operatorul << definit in interfata ProdusElectronic |
| - | } | + | } |
| - | for (int i = 0; i < nrProduse; i++) | + | for (int i = 0; i < nrProduse; i++) |
| - | { | + | { |
| - | delete produse[i]; | + | delete produse[i]; |
| - | } | + | } |
| - | delete[] produse; | + | delete[] produse; |
| - | return 0; | + | return 0; |
| } | } | ||
| </code> | </code> | ||
| Line 396: | Line 396: | ||
| <note tip>În mod similar, procedăm și pentru ceilalți operatori, indiferent dacă sunt supraîncărcați ca **funcții membre** sau ca **funcții friend**. Acești operatori vor fi supraîncărcați **exclusiv** în **clasa de bază**, iar comportamentul lor specific poate fi ulterior personalizat în **clasele derivate** prin intermediul **suprascrierii**. | <note tip>În mod similar, procedăm și pentru ceilalți operatori, indiferent dacă sunt supraîncărcați ca **funcții membre** sau ca **funcții friend**. Acești operatori vor fi supraîncărcați **exclusiv** în **clasa de bază**, iar comportamentul lor specific poate fi ulterior personalizat în **clasele derivate** prin intermediul **suprascrierii**. | ||
| - | Acest lucru se realizează prin definirea unor **funcții virtual pure** în clasa de bază, care stabilesc comportamentul operatorului respectiv în **subclase**. Clasele derivate vor implementa aceste **funcții virtuale**, asigurând astfel logica specifică operatorului în funcție de cerințele fiecărei clase. Această abordare permite un design flexibil și robust, bazat pe mecanismul de **run time polymorphism**.</note> | + | Acest lucru se realizează prin definirea unor **metode virtual pure** în clasa de bază, care stabilesc comportamentul operatorului respectiv în **subclase**. Clasele derivate vor implementa aceste **metode virtuale**, asigurând astfel logica specifică operatorului în funcție de cerințele fiecărei clase. Această abordare permite un design flexibil și robust, bazat pe mecanismul de **run time polymorphism**.</note> |
| ==== Concluzii ==== | ==== Concluzii ==== | ||