El polimorfismo es uno de los pilares fundamentales de la Programación Orientada a Objetos (POO). Permite que una función o un método se comporte de diferentes maneras según el objeto que lo invoque. En C++, el polimorfismo se puede lograr principalmente a través de la herencia y las funciones virtuales.

Conceptos Clave

  1. Polimorfismo en Tiempo de Compilación (Estático):

    • Sobrecarga de funciones.
    • Sobrecarga de operadores.
  2. Polimorfismo en Tiempo de Ejecución (Dinámico):

    • Funciones virtuales.
    • Clases abstractas.

Polimorfismo en Tiempo de Compilación

Sobrecarga de Funciones

La sobrecarga de funciones permite definir múltiples funciones con el mismo nombre pero con diferentes parámetros.

#include <iostream>
using namespace std;

class Print {
public:
    void show(int i) {
        cout << "Integer: " << i << endl;
    }

    void show(double d) {
        cout << "Double: " << d << endl;
    }

    void show(string s) {
        cout << "String: " << s << endl;
    }
};

int main() {
    Print p;
    p.show(5);
    p.show(3.14);
    p.show("Hello, World!");
    return 0;
}

Sobrecarga de Operadores

La sobrecarga de operadores permite definir o modificar el comportamiento de los operadores para los objetos de una clase.

#include <iostream>
using namespace std;

class Complex {
private:
    float real;
    float imag;
public:
    Complex() : real(0), imag(0) {}
    Complex(float r, float i) : real(r), imag(i) {}

    Complex operator + (const Complex& obj) {
        Complex temp;
        temp.real = real + obj.real;
        temp.imag = imag + obj.imag;
        return temp;
    }

    void display() {
        cout << "Real: " << real << " Imaginary: " << imag << endl;
    }
};

int main() {
    Complex c1(3.3, 4.4), c2(1.1, 2.2);
    Complex c3 = c1 + c2;
    c3.display();
    return 0;
}

Polimorfismo en Tiempo de Ejecución

Funciones Virtuales

Las funciones virtuales permiten que una función en una clase base sea sobrescrita en una clase derivada. Esto se logra utilizando la palabra clave virtual.

#include <iostream>
using namespace std;

class Base {
public:
    virtual void show() {
        cout << "Base class" << endl;
    }
};

class Derived : public Base {
public:
    void show() override {
        cout << "Derived class" << endl;
    }
};

int main() {
    Base* b;
    Derived d;
    b = &d;
    b->show();  // Output: Derived class
    return 0;
}

Clases Abstractas

Una clase abstracta es una clase que no puede ser instanciada y se utiliza como base para otras clases. Contiene al menos una función virtual pura.

#include <iostream>
using namespace std;

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

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;
}

Ejercicios Prácticos

Ejercicio 1: Sobrecarga de Funciones

Crea una clase Calculator que tenga funciones sobrecargadas para sumar dos enteros, dos flotantes y dos cadenas.

Ejercicio 2: Funciones Virtuales

Crea una clase base Animal con una función virtual makeSound(). Deriva dos clases Dog y Cat que sobrescriban la función makeSound() para imprimir "Woof" y "Meow" respectivamente. Crea un arreglo de punteros a Animal y llama a makeSound() para cada uno.

Soluciones

Solución Ejercicio 1

#include <iostream>
using namespace std;

class Calculator {
public:
    int add(int a, int b) {
        return a + b;
    }

    float add(float a, float b) {
        return a + b;
    }

    string add(string a, string b) {
        return a + b;
    }
};

int main() {
    Calculator calc;
    cout << "Sum of integers: " << calc.add(5, 3) << endl;
    cout << "Sum of floats: " << calc.add(2.5f, 3.5f) << endl;
    cout << "Sum of strings: " << calc.add("Hello, ", "World!") << endl;
    return 0;
}

Solución Ejercicio 2

#include <iostream>
using namespace std;

class Animal {
public:
    virtual void makeSound() = 0;
};

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* animals[2];
    animals[0] = new Dog();
    animals[1] = new Cat();

    for (int i = 0; i < 2; ++i) {
        animals[i]->makeSound();
    }

    for (int i = 0; i < 2; ++i) {
        delete animals[i];
    }

    return 0;
}

Conclusión

El polimorfismo es una característica poderosa de la POO que permite que los objetos de diferentes clases sean tratados a través de una interfaz común. Esto facilita la extensibilidad y la mantenibilidad del código. En este módulo, hemos explorado tanto el polimorfismo en tiempo de compilación como en tiempo de ejecución, proporcionando una base sólida para su aplicación en proyectos más complejos.

© Copyright 2024. Todos los derechos reservados