El polimorfisme és un concepte fonamental en la programació orientada a objectes (POO) que permet que una interfície única representi diferents tipus d'objectes. En C++, el polimorfisme es pot aconseguir principalment mitjançant funcions virtuals i herència. Aquest mòdul explorarà els conceptes clau del polimorfisme, com implementar-lo i com utilitzar-lo de manera efectiva.

Conceptes Clau

  1. Polimorfisme en Temps de Compilació vs. Polimorfisme en Temps d'Execució:

    • Polimorfisme en Temps de Compilació: També conegut com a polimorfisme estàtic, es refereix a la sobrecàrrega de funcions i operadors.
    • Polimorfisme en Temps d'Execució: També conegut com a polimorfisme dinàmic, es refereix a l'ús de funcions virtuals i herència per permetre que una funció es comporti de manera diferent segons l'objecte que la crida.
  2. Funcions Virtuals:

    • Les funcions virtuals permeten que una funció definida en una classe base sigui sobreescrita per una funció amb la mateixa signatura en una classe derivada.
  3. Classes Abstractes i Funcions Pures Virtuals:

    • Una classe abstracta és una classe que no es pot instanciar i que sovint conté una o més funcions pures virtuals. Una funció pura virtual és una funció que es defineix amb = 0 i ha de ser sobreescrita en una classe derivada.

Exemples Pràctics

Exemple 1: Funcions Virtuals

#include <iostream>
using namespace std;

class Animal {
public:
    virtual void makeSound() {
        cout << "Some generic animal sound" << endl;
    }
};

class Dog : public Animal {
public:
    void makeSound() override {
        cout << "Woof!" << endl;
    }
};

class Cat : public Animal {
public:
    void makeSound() override {
        cout << "Meow!" << endl;
    }
};

int main() {
    Animal* animal1 = new Dog();
    Animal* animal2 = new Cat();

    animal1->makeSound(); // Output: Woof!
    animal2->makeSound(); // Output: Meow!

    delete animal1;
    delete animal2;

    return 0;
}

Explicació

  1. Classe Base Animal:

    • Conté una funció virtual makeSound() que es pot sobreescriure en classes derivades.
  2. Classes Derivades Dog i Cat:

    • Sobrecarreguen la funció makeSound() per proporcionar una implementació específica.
  3. Polimorfisme en Temps d'Execució:

    • En el main(), es creen objectes de Dog i Cat però es tracten com a objectes de tipus Animal. Quan es crida makeSound(), s'executa la versió correcta de la funció segons el tipus real de l'objecte.

Exemple 2: Classes Abstractes i Funcions Pures Virtuals

#include <iostream>
using namespace std;

class Shape {
public:
    virtual void draw() = 0; // Funció pura virtual
};

class Circle : public Shape {
public:
    void draw() override {
        cout << "Drawing Circle" << endl;
    }
};

class Square : public Shape {
public:
    void draw() override {
        cout << "Drawing Square" << endl;
    }
};

int main() {
    Shape* shape1 = new Circle();
    Shape* shape2 = new Square();

    shape1->draw(); // Output: Drawing Circle
    shape2->draw(); // Output: Drawing Square

    delete shape1;
    delete shape2;

    return 0;
}

Explicació

  1. Classe Abstracta Shape:

    • Conté una funció pura virtual draw(), la qual cosa fa que Shape sigui una classe abstracta.
  2. Classes Derivades Circle i Square:

    • Implementen la funció draw().
  3. Polimorfisme en Temps d'Execució:

    • En el main(), es creen objectes de Circle i Square però es tracten com a objectes de tipus Shape. Quan es crida draw(), s'executa la versió correcta de la funció segons el tipus real de l'objecte.

Exercicis Pràctics

Exercici 1: Implementar Polimorfisme

Crea una classe base Vehicle amb una funció virtual move(). Després, crea dues classes derivades Car i Bicycle que sobrecarreguin la funció move() per proporcionar una implementació específica. Finalment, crea un programa que utilitzi polimorfisme per cridar la funció move() en objectes de tipus Vehicle.

Solució

#include <iostream>
using namespace std;

class Vehicle {
public:
    virtual void move() = 0; // Funció pura virtual
};

class Car : public Vehicle {
public:
    void move() override {
        cout << "Car is moving" << endl;
    }
};

class Bicycle : public Vehicle {
public:
    void move() override {
        cout << "Bicycle is moving" << endl;
    }
};

int main() {
    Vehicle* vehicle1 = new Car();
    Vehicle* vehicle2 = new Bicycle();

    vehicle1->move(); // Output: Car is moving
    vehicle2->move(); // Output: Bicycle is moving

    delete vehicle1;
    delete vehicle2;

    return 0;
}

Consells i Errors Comuns

  1. No oblidis el virtual:

    • Assegura't de declarar les funcions com a virtual en la classe base per permetre el polimorfisme en temps d'execució.
  2. Destructors Virtuals:

    • Si una classe conté funcions virtuals, és una bona pràctica declarar el destructor com a virtual per assegurar una correcta neteja de recursos.
  3. Classes Abstractes:

    • Recorda que no pots instanciar una classe abstracta directament. Només pots crear objectes de les seves classes derivades.

Resum

En aquesta secció, hem après sobre el polimorfisme en C++, incloent-hi el polimorfisme en temps de compilació i en temps d'execució. Hem explorat com utilitzar funcions virtuals i classes abstractes per implementar polimorfisme i hem vist exemples pràctics per il·lustrar aquests conceptes. A més, hem proporcionat exercicis per reforçar l'aprenentatge i consells per evitar errors comuns. Amb aquests coneixements, estàs preparat per aplicar el polimorfisme en els teus projectes de C++.

© Copyright 2024. Tots els drets reservats