Entendiendo el Polimorfismo en C++: Guía Práctica
La palabra polimorfismo significa tener muchas formas. Típicamente, el polimorfismo ocurre cuando hay una jerarquía de clases y están relacionadas por herencia.
El polimorfismo en C++ significa que una llamada a una función miembro causará que una función diferente sea ejecutada dependiendo del tipo de objeto que invoque la función.
Considera el siguiente ejemplo donde una clase base ha sido derivada por otras dos clases:
#include <iostream>
using namespace std;
class Forma {
protected:
int ancho, alto;
public:
Forma(int a = 0, int b = 0) {
ancho = a;
alto = b;
}
int area() {
cout << "Área de clase padre:" << endl;
return 0;
}
};
class Rectangulo: public Forma {
public:
Rectangulo(int a = 0, int b = 0): Forma(a, b) { }
int area() {
cout << "Área de clase Rectángulo:" << endl;
return (ancho * alto);
}
};
class Triangulo: public Forma {
public:
Triangulo(int a = 0, int b = 0): Forma(a, b) { }
int area() {
cout << "Área de clase Triángulo:" << endl;
return (ancho * alto / 2);
}
};
// Función principal para el programa
int main() {
Forma *forma;
Rectangulo rec(10, 7);
Triangulo tri(10, 5);
// almacenar la dirección de Rectángulo
forma = &rec;
// llamar área de rectángulo.
forma->area();
// almacenar la dirección de Triángulo
forma = &tri;
// llamar área de triángulo.
forma->area();
return 0;
}
Cuando el código anterior se compila y ejecuta, produce el siguiente resultado:
Área de clase padre:
Área de clase padre:
La razón de la salida incorrecta es que la llamada a la función area() está siendo establecida una vez por el compilador como la versión definida en la clase base. Esto se llama resolución estática de la llamada a función, o enlace estático - la llamada a función se fija antes de que el programa se ejecute. Esto también se llama a veces enlace temprano porque la función area() se establece durante la compilación del programa.
Pero ahora, hagamos una ligera modificación en nuestro programa y precedamos la declaración de area() en la clase Forma con la palabra clave virtual para que se vea así:
class Forma {
protected:
int ancho, alto;
public:
Forma(int a = 0, int b = 0) {
ancho = a;
alto = b;
}
virtual int area() {
cout << "Área de clase padre:" << endl;
return 0;
}
};
Después de esta ligera modificación, cuando el código del ejemplo anterior se compila y ejecuta, produce el siguiente resultado:
Área de clase Rectángulo
Área de clase Triángulo
Esta vez, el compilador mira el contenido del puntero en lugar de su tipo. Por lo tanto, ya que las direcciones de objetos de las clases tri y rec se almacenan en *forma, la respectiva función area() es llamada.
Como puedes ver, cada una de las clases hijas tiene una implementación separada para la función area(). Así es como el polimorfismo se usa generalmente. Tienes diferentes clases con una función del mismo nombre, e incluso los mismos parámetros, pero con diferentes implementaciones.
Función Virtual
Una función virtual es una función en una clase base que se declara usando la palabra clave virtual. Definir en una clase base una función virtual, con otra versión en una clase derivada, le indica al compilador que no queremos enlace estático para esta función.
Lo que queremos es que la selección de la función a ser llamada en cualquier punto del programa se base en el tipo de objeto para el cual es llamada. Este tipo de operación se refiere como enlace dinámico, o enlace tardío.
Funciones Virtuales Puras
Es posible que quieras incluir una función virtual en una clase base para que pueda ser redefinida en una clase derivada para adaptarse a los objetos de esa clase, pero que no hay una definición significativa que puedas dar para la función en la clase base.
Podemos cambiar la función virtual area() en la clase base a lo siguiente:
class Forma {
protected:
int ancho, alto;
public:
Forma(int a = 0, int b = 0) {
ancho = a;
alto = b;
}
// función virtual pura
virtual int area() = 0;
};
El = 0 le dice al compilador que la función no tiene cuerpo y la función virtual anterior será llamada función virtual pura.
Lenguaje C
- Dominando los Operadores en C++: Guía Completa con Ejemplos Prácticos
- Cómo Pasar Arrays a Funciones en C++: Guía Práctica
- Clases y Objetos en C++: Guía Práctica de Programación Orientada a Objetos
- Funciones y clases amigas en C++: dominando el control de acceso
- Dominando las plantillas de clase en C++: guía práctica
- Sobrecarga de operadores en C++: Guía práctica con ejemplos de código
- Entendiendo las Clases de Almacenamiento en C++: Alcance, Vida y Uso
- Dominando la Sobrecarga en C++: Funciones y Operadores Explicados
- Dominando la Abstracción de Datos en C++: Simplifica el Diseño con Separación Interfaz-Implementación
- Encapsulamiento de Datos en C++: Protege tu Código
- Interfaces en C++: Dominando Clases Abstractas y Funciones Virtuales Puras