¿Qué es una función virtual?

Una función virtual es una función, definida en una superclase, que debe estar presente en una subclase para que esa subclase tenga una definición de clase completa. Las funciones virtuales se basan en un paradigma de programación orientado a objetos llamado herencia virtual, que se ve más comúnmente en C ++ usando la palabra clave «virtual». Para definir una función virtual, se necesitan dos clases, una superclase y una subclase. La superclase es donde la función se declara por primera vez y posiblemente se define. La subclase es donde se define la función, o se anula, dependiendo de si la función se definió en la superclase.

La función virtual se puede definir de dos formas. Primero, se puede definir como un código auxiliar, en el que tiene un cuerpo vacío y no hace nada. En segundo lugar, podría definirse como una función virtual pura, donde se define como NULL en el archivo de encabezado de la superclase.

Ambas metodologías tienen ventajas y desventajas. Definir una función como un stub asegura que todas las subclases tengan alguna implementación, incluso si no hace nada. Sin embargo, si uno se olvida de anular la función e implementarla correctamente en una subclase, no aparecerán errores o advertencias para señalar esto. Definir una función virtual pura, por otro lado, requiere que cada subclase tenga su propia definición de la función, y aparecerán errores si este no es el caso.

Sin embargo, las funciones virtuales están sujetas a las mismas reglas de herencia que las funciones no virtuales, por lo que es posible que las jerarquías de herencia con más de dos niveles no requieran definiciones explícitas de funciones virtuales. Por ejemplo, se puede considerar una clase A que declara una función virtual, que se implementa en la subclase B. La clase B tiene una subclase propia, la clase C. La clase C no requiere una definición explícita de la función de la clase A, porque hereda la definición de la clase B. Si es necesario, la clase C podría anular la función de la clase B, o podría anular la función de la clase B al mismo tiempo que la llama.

En el otro extremo, las funciones virtuales no tienen que definirse en una subclase si se declaran virtuales en esa subclase. Por ejemplo, se puede considerar una clase A que declara una función virtual y tiene dos subclases, B y C. Además, uno podría imaginar que la clase B tiene subclases D y E, y la subclase C tiene subclases F y G.

Todas las clases B a G deben tener la función virtual de la clase A definida de alguna manera. Si la clase B tiene una implementación de la función de A, las clases D y E no necesitan rehacerla. Quizás las subclases de C necesitan implementar la función de A, pero ambas hacen algo diferente, por lo que definir la función en la clase C en sí no sería útil. En ese caso, la función puede declararse virtual en la clase C y no es necesaria una implementación.
Las funciones virtuales pueden ser desalentadoras de aprender, pero cuando se usan correctamente, pueden reducir la duplicación de código y hacer que el código sea mucho más fácil de entender en general. Sin embargo, existen muchas trampas con las funciones virtuales, especialmente en lo que respecta a la herencia múltiple. En la herencia múltiple, es posible que las funciones virtuales definidas de manera ambigua entren en conflicto entre sí, por lo que deben usarse con precaución en ese contexto.