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
-
Polimorfismo en Tiempo de Compilación (Estático):
- Sobrecarga de funciones.
- Sobrecarga de operadores.
-
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.
Curso de Programación en C++
Módulo 1: Introducción a C++
- Introducción a C++
- Configuración del Entorno de Desarrollo
- Sintaxis y Estructura Básica
- Variables y Tipos de Datos
- Entrada y Salida
Módulo 2: Estructuras de Control
Módulo 3: Funciones
- Introducción a las Funciones
- Parámetros de Función y Tipos de Retorno
- Sobrecarga de Funciones
- Recursión
Módulo 4: Arreglos y Cadenas
- Introducción a los Arreglos
- Arreglos Multidimensionales
- Introducción a las Cadenas
- Manipulación de Cadenas
Módulo 5: Punteros y Referencias
- Introducción a los Punteros
- Aritmética de Punteros
- Punteros y Arreglos
- Referencias
- Asignación Dinámica de Memoria
Módulo 6: Programación Orientada a Objetos
- Introducción a la POO
- Clases y Objetos
- Constructores y Destructores
- Herencia
- Polimorfismo
- Encapsulación y Abstracción
Módulo 7: Temas Avanzados
- Plantillas
- Manejo de Excepciones
- Entrada/Salida de Archivos
- Biblioteca Estándar de Plantillas (STL)
- Expresiones Lambda
- Multihilo