15: Polimorfismo y Funciones virtuales

Tabla de contenidos

15.1. Evolución de los programadores de C++
15.2. Upcasting
15.3. El problema
15.4. Funciones virtuales
15.5. Cómo implementa C++ la ligadura dinámica
15.6. ¿Por qué funciones virtuales?
15.7. Clases base abstractas y funciones virtuales puras
15.8. Herencia y la VTABLE
15.9. Sobrecargar y redefinir
15.10. funciones virtuales y constructores
15.11. Sobrecarga de operadores
15.12. Downcasting
15.13. Resumen
15.14. Ejercicios

El Polimorfismo (implementado en C++ con funciones virtuales) es la tercera característica esencial de un lenguaje orientado a objetos, después de la abstracción de datos y la herencia.

De hecho, nos provee de otra dimensión para la separación entre interfaz y la implementación, desacoplando el qué del cómo. El Polimorfismo permite mejorar la organización del código y su legibilidad así como la creación de programas extensibles que pueden "crecer" no sólo durante el desarrollo del proyecto, si no también cuando se deseen nuevas características.

La encapsulación crea nuevos tipos de datos combinando características y comportamientos. El control de acceso separa la interfaz de la implementación haciendo privados (private) los detalles. Estos tipos de organización son fácilmente entendibles por cualquiera que venga de la programación procedimental. Pero las funciones virtuales tratan de desunir en términos de tipos. En el Capítulo 14, usted vió como la herencia permitía tratar a un objeto como su propio tipo o como a su tipo base. Esta habilidad es básica debido a que permite a diferentes tipos (derivados del mismo tipo base) ser tratados como si fueran un único tipo, y un único trozo de código es capaz de trabajar indistintamente con todos. Las funciones virtuales permiten a un tipo expresar sus diferencias con respecto a otro similar si ambos han sido derivados del mismo tipo base. Esta distinción se consigue modificando las conductas de las funciones a las que se puede llamar a través de la clase base.

En este capítulo aprenderá sobre las funciones virtuales, empezando con ejemplos simples que le mostrará lo "desvirtual" del programa.

15.1. Evolución de los programadores de C++

Los programadores de C parecen conseguir pasarse a C++ en tres pasos. Al principio, como un "C mejorado", debido a que C++ le fuerza a declarar todas las funciones antes de usarlas y a que es mucho más sensible a la forma de usar las variables. A menudo se pueden encontrar errores en un programa C simplemente recompilándolo con un compilador de C++.

El segundo paso es la "programación basada en objetos", que significa que se pueden ver fácilmente los beneficios de la organización del código al agrupar estructuras de datos junto con las funciones que las manejan, la potencia de los constructores y los destructores, y quizás algo de herencia simple. La mayoría de los programadores que han trabajado durante un tiempo con C ven la utilidad de esto porque es lo que intentan hacer cuando crean una librería. Con C++ usted recibe la ayuda del compilador.

Usted se puede encontrar atascado en el nivel de "programación basada en objetos" debido a que es de fácil acceso y no requiere mucho esfuerzo mental. Es también sencillo sentir cómo está creando tipos de datos - usted hace clases y objetos, envía mensajes a esos objetos, y todo es bonito y pulcro.

Pero no sea tonto. Si se para aquí, se está perdiendo una de las más importantes partes del lenguaje, que significa el salto a la verdadera programación orientada a objetos. Y esto se consigue únicamente con las funciones virtuales.

Las funciones virtuales realzan el concepto de tipo en lugar de simplemente encapsular código dentro de estructuras y dejarlo detrás de un muro, por lo que son, sin lugar a dudas, el concepto más difícil a desentrañar por los nuevos programadores en C++. Sin embargo, son también el punto decisivo para comprender la programación orientada a objetos. Si no usa funciones virtuales, todavía no entiende la POO.

Debido a que las funciones virtuales están intimamente unidas al concepto de tipo, y los tipos son el núcleo de la programación orientada a objetos, no existe analogía a las funciones virtuales dentro de los lenguajes procedurales. Como programador procedural, usted no tiene referente con el que comparar las funciones virtuales, al contrario de las otras características del lenguaje. Las características de un lenguaje procedural pueden ser entendidas en un nivel algorítmico, pero las funciones virtuales deben ser entendidas desde el punto de vista del diseño.