MyCodeSchool
Polimorfism în C++
mycodeschool.ro

🚀 Polimorfism în C++

Ghid complet cu teorie, exemple practice și exerciții interactive

📚 Ce este Polimorfismul?

Polimorfismul este unul dintre cei patru piloni ai programării orientate pe obiecte (OOP), alături de încapsulare, moștenire și abstractizare.

Termenul provine din greacă: poly (multe) + morphe (forme), însemnând capacitatea de a avea multiple forme.

În C++, polimorfismul permite obiectelor de tipuri diferite să fie tratate prin aceeași interfață, permițând cod mai flexibil și mai ușor de întreținut.

Clasă de Bază
Clasă Derivată 1
Clasă Derivată 2
Clasă Derivată 3

🎯 Tipuri de Polimorfism

Compile-Time
Runtime

Polimorfism la Compile-Time (Static)

Rezolvat în timpul compilării. Include:

  • Supraîncărcarea funcțiilor (Function Overloading)
  • Supraîncărcarea operatorilor (Operator Overloading)
  • Template-uri

1. Supraîncărcarea Funcțiilor

#include <iostream>
using namespace std;

class Calculator {
public:
    // Funcții cu același nume dar parametri diferiți
    int add(int a, int b) {
        return a + b;
    }
    
    double add(double a, double b) {
        return a + b;
    }
    
    int add(int a, int b, int c) {
        return a + b + c;
    }
};

2. Supraîncărcarea Operatorilor

class Complex {
private:
    double real, imag;
    
public:
    Complex(double r = 0, double i = 0) : real(r), imag(i) {}
    
    // Supraîncărcarea operatorului +
    Complex operator+(const Complex& c) {
        return Complex(real + c.real, imag + c.imag);
    }
    
    // Supraîncărcarea operatorului <<
    friend ostream& operator<<(ostream& out, const Complex& c) {
        out << c.real << " + " << c.imag << "i";
        return out;
    }
};

Polimorfism la Runtime (Dinamic)

Rezolvat în timpul execuției. Se realizează prin:

  • Funcții virtuale
  • Pointeri și referințe la clasa de bază
  • Tabele de funcții virtuale (vtable)

Exemplu Complet - Sistem de Forme Geometrice

#include <iostream>
#include <vector>
#include <cmath>
using namespace std;

// Clasă de bază abstractă
class Shape {
protected:
    string name;
    
public:
    Shape(const string& n) : name(n) {}
    
    // Funcții virtuale pure - face clasa abstractă
    virtual double area() const = 0;
    virtual double perimeter() const = 0;
    
    // Funcție virtuală normală
    virtual void display() const {
        cout << "Shape: " << name << endl;
        cout << "Area: " << area() << endl;
        cout << "Perimeter: " << perimeter() << endl;
    }
    
    // Destructor virtual - important pentru polimorfism!
    virtual ~Shape() {}
};

// Clasă derivată - Cerc
class Circle : public Shape {
private:
    double radius;
    
public:
    Circle(double r) : Shape("Circle"), radius(r) {}
    
    double area() const override {
        return M_PI * radius * radius;
    }
    
    double perimeter() const override {
        return 2 * M_PI * radius;
    }
};

// Clasă derivată - Dreptunghi
class Rectangle : public Shape {
private:
    double width, height;
    
public:
    Rectangle(double w, double h) 
        : Shape("Rectangle"), width(w), height(h) {}
    
    double area() const override {
        return width * height;
    }
    
    double perimeter() const override {
        return 2 * (width + height);
    }
};

// Clasă derivată - Triunghi
class Triangle : public Shape {
private:
    double a, b, c; // laturile
    
public:
    Triangle(double side1, double side2, double side3) 
        : Shape("Triangle"), a(side1), b(side2), c(side3) {}
    
    double area() const override {
        // Formula lui Heron
        double s = (a + b + c) / 2;
        return sqrt(s * (s - a) * (s - b) * (s - c));
    }
    
    double perimeter() const override {
        return a + b + c;
    }
};

int main() {
    // Vector de pointeri la clasa de bază
    vector<Shape*> shapes;
    
    // Adăugăm diferite forme
    shapes.push_back(new Circle(5));
    shapes.push_back(new Rectangle(4, 6));
    shapes.push_back(new Triangle(3, 4, 5));
    
    // Polimorfism în acțiune!
    cout << "=== Demonstrație Polimorfism ===\n\n";
    
    for (const auto& shape : shapes) {
        shape->display();  // Apelează metoda corectă pentru fiecare tip
        cout << "-----------------\n";
    }
    
    // Calculăm aria totală
    double totalArea = 0;
    for (const auto& shape : shapes) {
        totalArea += shape->area();
    }
    cout << "\nAria totală: " << totalArea << endl;
    
    // Eliberăm memoria
    for (auto& shape : shapes) {
        delete shape;
    }
    
    return 0;
}

⚡ Concepte Avansate

1. Funcții Virtuale Pure și Clase Abstracte

Clasă abstractă: O clasă care conține cel puțin o funcție virtuală pură.

Funcție virtuală pură: Declarată cu = 0 și TREBUIE implementată în clasele derivate.

class Animal {  // Clasă abstractă
public:
    virtual void makeSound() = 0;  // Funcție virtuală pură
    
    // Poate avea și funcții normale
    void sleep() {
        cout << "Zzz..." << endl;
    }
};

2. Tabela de Funcții Virtuale (vtable)

Când o clasă conține funcții virtuale, compilatorul creează o vtable (virtual table) pentru acea clasă.

  • Fiecare obiect conține un pointer ascuns către vtable-ul clasei sale
  • vtable conține pointeri către implementările funcțiilor virtuale
  • Permite legarea dinamică (dynamic binding) la runtime

3. Cuvântul cheie 'override' (C++11)

class Base {
public:
    virtual void func(int x);
};

class Derived : public Base {
public:
    // 'override' garantează că suprascrii o funcție virtuală existentă
    void func(int x) override;
    
    // Eroare de compilare dacă funcția nu există în bază!
    // void funk(int x) override;  // Typo detectat!
};

4. Cuvântul cheie 'final'

class Base {
public:
    virtual void func();
};

class Derived final : public Base {  // Nu poate fi moștenită
public:
    void func() final;  // Nu poate fi suprascrisă
};

🎮 Exemplu Practic: Sistem de Joc RPG

#include <iostream>
#include <vector>
#include <memory>
using namespace std;

// Clasă de bază pentru personaje
class Character {
protected:
    string name;
    int health;
    int damage;
    
public:
    Character(const string& n, int h, int d) 
        : name(n), health(h), damage(d) {}
    
    virtual void attack() const {
        cout << name << " attacks for " << damage << " damage!" << endl;
    }
    
    virtual void specialAbility() const = 0;
    
    virtual void displayInfo() const {
        cout << "[" << getClass() << "] " << name 
             << " - HP: " << health << ", DMG: " << damage << endl;
    }
    
    virtual string getClass() const = 0;
    
    virtual ~Character() = default;
};

// Clasă Warrior
class Warrior : public Character {
private:
    int armor;
    
public:
    Warrior(const string& n) 
        : Character(n, 150, 25), armor(50) {}
    
    void attack() const override {
        cout << name << " swings his mighty sword for " 
             << damage << " damage!" << endl;
    }
    
    void specialAbility() const override {
        cout << name << " uses Shield Bash! Stuns the enemy!" << endl;
    }
    
    string getClass() const override {
        return "Warrior";
    }
};

// Clasă Mage
class Mage : public Character {
private:
    int mana;
    
public:
    Mage(const string& n) 
        : Character(n, 80, 40), mana(200) {}
    
    void attack() const override {
        cout << name << " casts Fireball for " 
             << damage << " damage!" << endl;
    }
    
    void specialAbility() const override {
        cout << name << " casts Meteor Storm! Massive area damage!" << endl;
    }
    
    string getClass() const override {
        return "Mage";
    }
};

// Clasă Rogue
class Rogue : public Character {
private:
    int critChance;
    
public:
    Rogue(const string& n) 
        : Character(n, 100, 35), critChance(30) {}
    
    void attack() const override {
        cout << name << " strikes from the shadows for " 
             << damage << " damage!" << endl;
    }
    
    void specialAbility() const override {
        cout << name << " vanishes! Becomes invisible!" << endl;
    }
    
    string getClass() const override {
        return "Rogue";
    }
};

int main() {
    // Folosim smart pointers pentru management automat al memoriei
    vector<unique_ptr<Character>> party;
    
    party.push_back(make_unique<Warrior>("Thorin"));
    party.push_back(make_unique<Mage>("Gandalf"));
    party.push_back(make_unique<Rogue>("Bilbo"));
    
    cout << "=== Party Members ===\n";
    for (const auto& member : party) {
        member->displayInfo();
    }
    
    cout << "\n=== Battle Begins! ===\n";
    for (const auto& member : party) {
        member->attack();
        member->specialAbility();
        cout << endl;
    }
    
    return 0;
}

🧩 Exerciții de Înțelegere a Polimorfismului

Important: Aceste exerciții demonstrează comportamentul subtil al funcțiilor virtuale vs non-virtuale.

Analizați cu atenție ce funcții sunt virtuale și predicționați output-ul ÎNAINTE de a rula codul!

🐸 Exemplu Original: Poveste cu Broască

#include <iostream>
using namespace std;

class fairy_tale {
public:
    void        act0(){ cout << "0 Început poveste originală\n"; }
    virtual void act1(){ cout << "1 Prințesa întâlnește broscoiul\n"; }
    void        act2(){ cout << "2 Prințesa sărută broscoiul\n"; }
    virtual void act3(){ cout << "3 Broscoiul se transformă în Prinț\n"; act4(); }
    virtual void act4(){ cout << "4 Și au trăit mulți ani fericiți\n"; act5(); }
    void        act5(){ cout << "5 Sfârșit fericit\n"; }
};

class unhappy_tale : public fairy_tale {
public:
    void        act0(){ cout << "0 Început poveste modificată\n"; act1(); }
    void        act2(){ cout << "2 Prințesa atinge broscoiul\n"; act3(); }
    void        act3(){ cout << "3 Broscoiul rămâne broscoi\n"; act4(); }
    void        act4(){ cout << "4 Prințesa fuge îngrozită\n"; act5(); }
    void        act5(){ cout << "5 Sfârșit nu prea fericit\n"; }
};

Exercițiul 1: 🍕 Restaurant Chain

class Restaurant {
public:
    void        openDoors()  { cout << "Opening at 10 AM\n"; serve(); }
    virtual void serve()     { cout << "Serving regular menu\n"; }
    void        takeOrder() { cout << "Taking order\n"; cook(); }
    virtual void cook()      { cout << "Cooking standard dish\n"; deliver(); }
    virtual void deliver()   { cout << "Waiter delivers food\n"; }
    void        closeDoors(){ cout << "Closing at 10 PM\n"; }
};

class FastFood : public Restaurant {
public:
    void        openDoors()  { cout << "24/7 Open\n"; serve(); }
    void        serve()     { cout << "Serving fast food menu\n"; takeOrder(); }
    void        cook()      { cout << "Quick frying\n"; deliver(); }
    void        deliver()   { cout << "Self-service counter\n"; }
};

// Test: Ce va afișa?
Restaurant* r = new FastFood();
r->openDoors();
delete r;

Exercițiul 2: 🎮 Game Combat System

class Fighter {
public:
    virtual void startCombat() { cout << "Fighter enters arena\n"; prepareWeapon(); }
    void        prepareWeapon() { cout << "Draws sword\n"; attack(); }
    virtual void attack()       { cout << "Basic sword slash\n"; defend(); }
    void        defend()       { cout << "Raises shield\n"; }
    virtual void victory()      { cout << "Fighter wins!\n"; }
};

class Ninja : public Fighter {
public:
    void        startCombat()  { cout << "Ninja appears from shadows\n"; prepareWeapon(); }
    void        prepareWeapon() { cout << "Throws shuriken\n"; attack(); }
    void        attack()       { cout << "Silent strike\n"; vanish(); }
    void        vanish()       { cout << "Disappears in smoke\n"; victory(); }
    void        victory()      { cout << "Ninja vanishes victoriously!\n"; }
};

// Test: Predicționați output-ul
Fighter* f = new Ninja();
f->startCombat();
delete f;

Exercițiul 3: 🚗 Vehicle Manufacturing

class CarFactory {
public:
    void        startProduction() { cout << "Starting assembly line\n"; buildChassis(); }
    virtual void buildChassis()   { cout << "Building standard chassis\n"; installEngine(); }
    virtual void installEngine()  { cout << "Installing V6 engine\n"; paint(); }
    void        paint()          { cout << "Painting in blue\n"; addInterior(); }
    virtual void addInterior()    { cout << "Standard seats\n"; }
};

class ElectricCarFactory : public CarFactory {
public:
    void        buildChassis()   { cout << "Building lightweight chassis\n"; installEngine(); }
    void        installEngine()  { cout << "Installing electric motor\n"; installBattery(); }
    void        installBattery() { cout << "Installing lithium battery\n"; paint(); }
    void        addInterior()    { cout << "Eco-friendly interior\n"; }
};

// Ce se va afișa?
CarFactory* factory = new ElectricCarFactory();
factory->startProduction();
delete factory;

Exercițiul 4: 📚 Online Course Platform

class Course {
public:
    virtual void start()      { cout << "Welcome to course\n"; showIntro(); }
    void        showIntro()  { cout << "Course introduction\n"; teach(); }
    virtual void teach()      { cout << "Teaching theory\n"; practice(); }
    virtual void practice()   { cout << "Solving exercises\n"; }
    void        evaluate()   { cout << "Final exam\n"; certificate(); }
    virtual void certificate(){ cout << "Course completed!\n"; }
};

class InteractiveCourse : public Course {
public:
    void        start()      { cout << "Interactive session begins\n"; showIntro(); }
    void        teach()      { cout << "Live coding session\n"; practice(); }
    void        practice()   { cout << "Pair programming\n"; evaluate(); }
    void        certificate(){ cout << "Digital badge earned!\n"; }
};

// Analizați fluxul
Course* c = new InteractiveCourse();
c->start();
delete c;

Exercițiul 5: 🎭 Theater Performance

class Play {
public:
    void        showtime()    { cout << "Curtains open\n"; act1(); }
    virtual void act1()        { cout << "Romeo meets Juliet\n"; intermission(); }
    void        intermission(){ cout << "15 minute break\n"; act2(); }
    virtual void act2()        { cout << "Balcony scene\n"; finale(); }
    virtual void finale()      { cout << "Tragic ending\n"; applause(); }
    void        applause()    { cout << "Standing ovation\n"; }
};

class ModernPlay : public Play {
public:
    void        act1()        { cout << "Texting instead of meeting\n"; intermission(); }
    void        act2()        { cout << "Video call scene\n"; finale(); }
    void        finale()      { cout << "Happy viral ending\n"; }
};

// Ce va afișa?
Play* p = new ModernPlay();
p->showtime();
delete p;

Exercițiul 6: 🏠 Smart Home System

class HomeSystem {
public:
    virtual void morning()      { cout << "6 AM wake up\n"; lights(); }
    void        lights()       { cout << "Lights on\n"; heating(); }
    virtual void heating()      { cout << "Temperature 20°C\n"; }
    void        security()     { cout << "Alarm disabled\n"; devices(); }
    virtual void devices()      { cout << "TV on news channel\n"; }
};

class SmartHome : public HomeSystem {
public:
    void        morning()      { cout << "AI: Good morning!\n"; lights(); coffee(); }
    void        heating()      { cout << "Smart thermostat 22°C\n"; security(); }
    void        coffee()       { cout << "Coffee machine starts\n"; }
    void        devices()      { cout << "Playing your playlist\n"; }
};

// Complex chain - predicționați!
HomeSystem* home = new SmartHome();
home->morning();
delete home;

Exercițiul 7: 🛍️ Shopping Experience

class Shop {
public:
    void        enter()        { cout << "Welcome!\n"; browse(); }
    virtual void browse()       { cout << "Looking at products\n"; select(); }
    virtual void select()       { cout << "Choosing item\n"; pay(); }
    void        pay()          { cout << "Cash payment\n"; wrap(); }
    virtual void wrap()         { cout << "Paper bag\n"; }
    void        exit()         { cout << "Thank you!\n"; }
};

class OnlineShop : public Shop {
public:
    void        enter()        { cout << "Loading website\n"; browse(); }
    void        browse()       { cout << "Scrolling catalog\n"; filter(); }
    void        filter()       { cout << "Applying filters\n"; select(); }
    void        select()       { cout << "Add to cart\n"; checkout(); }
    void        checkout()     { cout << "Proceed to checkout\n"; pay(); }
    void        wrap()         { cout << "Email confirmation\n"; exit(); }
};

// Testați înțelegerea
Shop* s = new OnlineShop();
s->enter();
delete s;

Exercițiul 8: 🎵 Music Player

class MusicPlayer {
public:
    virtual void powerOn()      { cout << "Device starting\n"; loadMusic(); }
    void        loadMusic()    { cout << "Loading tracks\n"; play(); }
    virtual void play()         { cout << "Playing music\n"; showDisplay(); }
    virtual void showDisplay()  { cout << "LCD display\n"; }
    void        stop()         { cout << "Music stopped\n"; powerOff(); }
    virtual void powerOff()     { cout << "Goodbye\n"; }
};

class StreamingPlayer : public MusicPlayer {
public:
    void        powerOn()      { cout << "Connecting WiFi\n"; login(); }
    void        login()        { cout << "Spotify login\n"; loadMusic(); }
    void        play()         { cout << "Streaming HD audio\n"; showDisplay(); }
    void        showDisplay()  { cout << "Album art display\n"; stop(); }
    void        powerOff()     { cout << "Saving playlist\n"; }
};

// Ce se întâmplă aici?
MusicPlayer* mp = new StreamingPlayer();
mp->powerOn();
delete mp;

Exercițiul 9: 🏥 Medical System

class Hospital {
public:
    void        admission()    { cout << "Patient registered\n"; triage(); }
    virtual void triage()       { cout << "Nurse assessment\n"; diagnose(); }
    virtual void diagnose()     { cout << "Doctor examination\n"; treat(); }
    void        treat()        { cout << "Standard treatment\n"; discharge(); }
    virtual void discharge()    { cout << "Patient leaves\n"; }
};

class EmergencyRoom : public Hospital {
public:
    void        admission()    { cout << "EMERGENCY!\n"; triage(); }
    void        triage()       { cout << "Immediate assessment\n"; stabilize(); }
    void        stabilize()    { cout << "Vitals stabilized\n"; diagnose(); }
    void        diagnose()     { cout << "Quick diagnosis\n"; urgentCare(); }
    void        urgentCare()   { cout << "Emergency procedure\n"; treat(); }
    void        discharge()    { cout << "Transfer to ward\n"; }
};

// Analizați cu atenție
Hospital* h = new EmergencyRoom();
h->admission();
delete h;

Exercițiul 10: 🎪 Circus Show

class CircusAct {
public:
    virtual void announce()     { cout << "Ladies and gentlemen!\n"; prepare(); }
    void        prepare()      { cout << "Setting up stage\n"; perform(); }
    virtual void perform()      { cout << "Basic juggling\n"; climax(); }
    virtual void climax()       { cout << "Amazing trick!\n"; bow(); }
    void        bow()          { cout << "Take a bow\n"; applause(); }
    virtual void applause()     { cout << "Crowd claps\n"; }
};

class MagicShow : public CircusAct {
public:
    void        announce()     { cout << "Behold the magic!\n"; mysterySounds(); }
    void        mysterySounds(){ cout << "Mysterious music\n"; prepare(); }
    void        perform()      { cout << "Rabbit from hat\n"; misdirect(); }
    void        misdirect()    { cout << "Look over there!\n"; climax(); }
    void        climax()       { cout << "Person disappears!\n"; reappear(); }
    void        reappear()     { cout << "Appears in audience!\n"; bow(); }
    void        applause()     { cout << "Standing ovation!\n"; }
};

// Final challenge!
CircusAct* act = new MagicShow();
act->announce();
delete act;

✏️ Exerciții Practice Avansate

Exercițiul 1: Sistem Bancar

Creați o ierarhie de clase pentru un sistem bancar:

  • Clasă de bază Account cu metode virtuale pentru deposit(), withdraw(), și calculateInterest()
  • Clase derivate: SavingsAccount, CurrentAccount, FixedDeposit
  • Implementați rate diferite de dobândă și reguli de retragere

Exercițiul 2: Sistem de Transport

Implementați o ierarhie pentru vehicule:

  • Clasă abstractă Vehicle cu metode pentru move(), refuel()
  • Clase derivate: Car, Bicycle, Airplane
  • Adăugați o funcție care primește un vector de vehicule și le face să se miște

Exercițiul 3: Calculator cu Operații

Creați un sistem de operații matematice folosind polimorfism:

  • Clasă de bază Operation cu metodă virtuală calculate()
  • Clase derivate pentru: Addition, Subtraction, Multiplication, Division
  • Implementați un calculator care procesează o listă de operații

🎯 Avantaje și Dezavantaje

✅ Avantaje

  • Cod mai flexibil și extensibil
  • Reutilizare eficientă a codului
  • Întreținere mai ușoară
  • Abstractizare puternică
  • Respectă principiul Open/Closed

⚠️ Dezavantaje

  • Overhead de performanță (vtable lookup)
  • Complexitate crescută pentru începători
  • Debugging mai dificil
  • Utilizare suplimentară de memorie
  • Nu poate fi folosit cu funcții inline

📝 Rezumat și Best Practices

Reguli de Aur:

  • ✨ Folosiți virtual pentru funcții care vor fi suprascrise
  • ✨ Întotdeauna declarați destructorul virtual în clasele de bază
  • ✨ Folosiți override în clasele derivate (C++11)
  • ✨ Preferați composition over inheritance când e posibil
  • ✨ Nu faceți toate funcțiile virtuale - doar cele necesare
  • ✨ Folosiți smart pointers pentru management automat al memoriei
  • ✨ Testați polimorfismul cu diferite tipuri de obiecte

Erori Comune de Evitat:

  • ❌ Uitarea destructorului virtual → memory leaks
  • ❌ Object slicing când copiați obiecte derivate în bază
  • ❌ Confuzia între overloading și overriding
  • ❌ Apelarea funcțiilor virtuale în constructor/destructor
  • ❌ Uitarea să implementezi funcțiile virtuale pure

🚀 Concluzie

Polimorfismul este unul dintre cele mai puternice concepte în C++, permițând cod elegant, flexibil și ușor de întreținut.

Stăpânirea polimorfismului vă va transforma dintr-un programator C++ începător într-unul avansat! 💪