En
el ejemplo que se ve en la figura 6 se observa una jerarquía
de clases. En todos los niveles de esta jerarquía está
contenida una función llamada Funcion_1().
Esta función no tiene por qué ser igual en todas las
clases, aunque es habitual que sea una función que efectúe
una operación muy parecida sobre distintos tipos de objetos.
Es
importante comprender que el compilador no decide en tiempo
de compilación cuál será la función
que se debe utilizar en un momento dado del programa. Esa decisión
se toma en tiempo de ejecución. A este proceso
de decisión en tiempo de ejecución se le denomina
vinculación dinámica o tardía,
en oposición a la habitual vinculación estática
o temprana, consistente en
decidir en tiempo de compilación qué función
se aplica en cada caso.
A
este tipo de funciones, incluidas en varios niveles de una jerarquía
de clases con el mismo nombre pero con distinta definición,
se les denomina funciones virtuales. Hay que insistir
en que la definición de la función en cada nivel es
distinta.
El
polimorfismo hace posible que un usuario pueda añadir
nuevas clases a una jerarquía sin modificar
o recompilar el código original. Esto quiere decir
que si desea añadir una nueva clase derivada es suficiente
con establecer la clase de la que deriva, definir sus nuevas variables
y funciones miembro, y compilar esta parte del código, ensamblándolo
después con lo que ya estaba compilado previamente.
Es
necesario comentar que las funciones virtuales son
algo menos eficientes que las funciones normales. A continuación
se explica, sin entrar en gran detalle, el funcionamiento de las
funciones virtuales. Cada clase que utiliza funciones
virtuales tiene un vector de punteros, uno
por cada función virtual, llamado v-table.
Cada uno de los punteros contenidos en ese vector apunta a la
función virtual apropiada para esa clase, que será,
habitualmente, la función virtual definida
en la propia clase. En el caso de que en esa clase no esté
definida la función virtual en cuestión,
el puntero de v-table apuntará a la función
virtual de su clase base más próxima en la
jerarquía, que tenga una definición propia de la función
virtual. Esto quiere decir que buscará primero en
la propia clase, luego en la clase anterior en el orden jerárquico
y se irá subiendo en ese orden hasta dar con una clase que
tenga definida la función buscada.
Cada
objeto creado de una clase que tenga una función virtual
contiene un puntero oculto a la v-table de
su clase. Mediante ese puntero accede a su v-table
correspondiente y a través de esta tabla accede a la definición
adecuada de la función virtual. Es este trabajo
extra el que hace que las funciones virtuales sean menos eficientes
que las funciones normales.
Como
ejemplo se puede suponer que la cuenta_joven y
la cuenta_empresarial antes descritas tienen una forma
distinta de abonar mensualmente el interés al saldo.
·
En la cuenta_joven, no se abonará el interés
pactado si el saldo es inferior a un límite.
· En la cuenta_empresarial se tienen
tres cantidades límite, a las cuales se aplican factores
de corrección en el cálculo del interés. El
cálculo de la cantidad abonada debe realizarse de la siguiente
forma:
1.
Si el saldo es menor que 50000, se aplica el interés establecido
previamente.
2. Si el saldo está entre 50000 y 500.000, se aplica 1.1
veces el interés establecido previamente.
3. Si el saldo es mayor a 500.000, se aplica 1.5 veces el interés
establecido
previamente.
El
código correspondiente quedaría de la siguiente forma:
|