- Encapsulación y extensión de tipos
- Herencia
- Polimorfismo
- Sobrecarga
- Funciones virtuales
- Miembros estáticos de una clase
- Plantillas de funciones
- Plantillas de clases
- Clases abstractas
Funciones virtuales
La palabra clave virtual es un especificador de la función que proporciona el mecanismo para la elección dinámica durante la fase de ejecución de una función miembro conveniente entre las funciones de la clase base y derivada. Las estructuras no pueden tener funciones virtuales. Puede usarse para el cambio de las declaraciones sólo de las funciones miembro.
La función virtual, igual que una corriente, debe tener un cuerpo ejecutable. Durante la llamada su semántica es la misma que la de las demás funciones.
Una función virtual puede ser sustituida en una clase derivada. La elección de qué tipo de definición de la función llamar para una función virtual, se hace de una forma dinámica (durante la fase de ejecución). Un caso típico es cuando la clase base contiene una función virtual, y las clases derivadas tienen sus versiones de esta función.
El puntero a la clase base puede indicar al objeto de la clase base o al objeto de la clase derivada. La elección de la función miembro va a ser realizada en la fase de ejecución y va a depender del tipo del objeto y no del tipo del puntero. Si no hay miembro del tipo derivado, por defecto se utiliza la función virtual de la clase base.
Los destructores siempre son virtuales, independientemente de que si están declarados con la palabra clave virtual o no.
Vamos a ver el uso de funciones virtuales en el ejemplo del programa MT5_Tetris.mq5. La clase base CTetrisShape con la función virtual Draw (dibujar) está definida en el archivo incluido MT5_TetrisShape.mqh.
//+------------------------------------------------------------------+
|
Luego, para cada clase derivada, esta función se implementa de acuerdo con las particularidades de la clase descendiente. Por ejemplo, la primera figura CTetrisShape1 tiene su propia implementación de la función Draw():
class CTetrisShape1 : public CTetrisShape
|
La figura cuadrado está descrita por la clase CTetrisShape6 y tiene su propia implementación del método Draw():
class CTetrisShape6 : public CTetrisShape
|
Dependiendo de qué clase ha sido creado el objeto, se llama a la función virtual de una u otra clase derivada.
void CTetrisField::NewShape()
|
Modificador override #
El modificador override indica que la función declarada deberá redefinir obligatoriamente el método de la clase padre. El uso de este modificador permite evitar errores en la redifinición, tales como el cambio casual de la signatura del método. Por ejemplo, en la clase básica se define el método func, que toma como argumento una variable del tipo int:
class CFoo |
A continuación, el método se redefine en la clase heredada:
class CBar : public CFoo |
Pero por error, el tipo de argumento cambia de int a short. De hecho, en este caso ya tiene lugar no la redefinición, sino la sobrecarga del método. Actuando de acuerdo con el algoritmo de definición de la función sobrecargada, en ciertas situaciones el compilador puede elegir el método definido en la clase básica, en lugar del método redefinido.
Para evitar errores semejantes, al método redefinido se le debe añadir claramente el modificador override.
class CBar : public CFoo |
Si durante la redefinición se cambia la signatura del método, el compilador no podrá encontrar en la clase padre un método con la misma signatura y dará un error de compilación:
'CBar::func' method is declared with 'override' specifier but does not override any base class method |
Modificador final #
El modificador final actúa al revés, prohibiendo la redefinición del método en las clases heredadas. Si la implementación de un método es autosuficiente y ha finalizado por completo, declárela con el modificador final, para que haya garantías de que no será modificada en lo sucesivo.
class CFoo |
Al intentar redefinir un método con el modificador final, como se muestra en el ejemplo de más arriba, el compilador dará error:
'CFoo::func' method declared as 'final' cannot be overridden by 'CBar::func' |
Véase también