![]() |
|---|
![]() |
![]() |
![]() |
Funciones virtuales
Con frecuencia en el
trabajo de programaci�n ocurre que tenemos que utilizar una parte de una funci�n que ya
esta hecha y probada pero debe modificarse el comportamiento de otros elementos de esa
misma funci�n.
Veamos un ejemplo de esto:
La funci�n �traslada� de
la clase TCirculo nos permite trasladar de
posici�n los objetos de esa clase. El
contenido de esa funci�n es esencialmente el siguiente:
| ~ ~ ~ ~ ~
Borra(); IncrementaX(ValorX); IncrementaY(ValorY); Muestra(); ~ ~ ~ ~ ~ |
Esa clase resulta en
extremo �til para heredar de ella y construir una clase TIconoFuente que nos permita hacer un icono que
represente una fuente de voltaje, pero para ello tenemos que a�adir al c�rculo el dibujo
de una sinosoide.
Esta modificaci�n sabemos
como hacerla. Simplemente pondremos en la
clase TIconoFuente las funciones Muestra() y Borra() donde se incluir�an las anteriores de TC�rculo y con las l�neas de programa necesarias
para poner en el centro del c�rculo la sinosoide.
Tendriamos as� que la
nueva funci�n Muestra() quedar�a:
| void TIconoFuente::Muestra () { TCirculo :: Muestra(); for(float i=0;i<6.14;i+=0.01) { float X = MiX()-0.5*MiRadio() + i*0.5*MiRadio()/3.07; float Y = MiY()-0.5*MiRadio()*sin(i); putpixel(X,Y,EGA_RED); } } |
Pero cuando queremos desplazar ahora el icono como
llamamos a Traslada() de la clase TIconoFuente las funciones que actuar�n son Muestra() y Borra()
de TCirculo y por tanto ellas ni borraran la
sinosoide ni la volver�n a pintar. Esto nos
obligar�a a volver a escribir Traslada() en TIconoFuente con lo que la propiedad de herencia
perderia eficiencia.
Para resolver este tipo de situaciones C++ nos brinda las
funciones virtuales.
Una funci�n virtual es aquella que
permite a las clases herederas de la que ella es miembro tener funciones con el mismo
nombre y los mismos parametros y que el sistema las identifica en dependencia de la clase
a la que pertenece el objeto que las llama.
Si regresamos a nuestro
ejemplo tenemos que en la funci�n Traslada de
la clase TCirculo est�n incluidas las funciones
Borra() y Muestra() , esas funciones existen
tambien con los mismos nombres y parametros en la clase TIconoFuente y de esto proven�a el problema que
encontramos, o sea al llamar desde un objeto de TIconoFuente
a Traslada
se llama a las funciones Borra() y Muestra() de TCirculo cuando queriamos que fueran llamadas las Borra() y Muestra() y TIconoFuente.
Las funciones virtuales nos resuelven este problema. Si declaramos en TCirculo a
Borra() y Muestra() como virtuales y tambi�n lo hacemos esta es una
condici�n obligatoria en C++, una vez que una funci�n es declarada virtual en una clase debe ser declarada tambi�n
como tal en todas las herederas en TIconoFuente
el sistema identificar�, en tiempo de ejecuci�n, a que clase pertenece el objeto desde
donde se llama a Traslada y en correspondencia
ejecutar� a Borra() y Muestra().
La biblioteca Circulo.h
quedar� entonces as�:
| class TCirculo { private: ~ ~ ~ ~ ~ public: ~ ~ ~ ~ ~ virtual void Muestra (void); virtual void Borra (void); }; void TCirculo::MueveEn (float EnX,float EnY) { Borra(); posx += EnX; posy += EnY; Muestra(); } void TCirculo::Muestra () { ~ ~ ~ ~ ~ } void TCirculo::Borra
() |
| class TIconoFuente : public TCirculo { public: TIconoFuente (float PosxP,float PosyP,float radioP, unsigned int ColorP=WHITE) : TCirculo (PosxP, PosyP, radioP, ColorP=WHITE) {} virtual void Muestra (void); virtual void Borra (void); }; void
TIconoFuente::Muestra () void TIconoFuente::Borra () |
La clase TIconoFuente puede ahora aprovechar la funci�n
Traslada de TCirculo ya que las funciones Borra() y Muestra() son virtuales. Es muy instructivo correr paso a paso un programa
de este tipo para ver como se va de una biblioteca a otra seg�n sea el objeto que
invoque a Traslada().
![]() |
![]() |