Titulo.jpg (10742 bytes)
FlechaI.jpg (2886 bytes) casa.jpg (31539 bytes) FlechaD.jpg (2791 bytes)

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();
    ~ ~ ~ ~ ~             

 La funci�n Borra() elimina el c�rculo que estuviera dibujado anteriormente, las funciones Incrementa...  le dan un nuevo valor a X y Y y Muestra() pone en pantalla, en la nueva posici�n, el c�rculo.

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);
      }
}

 donde como se ve hacemos primero una llamada a la Muestra() de TCirculo y despu�s aparece un c�clo que pinta la sinosoide.

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 ()
{      ~ ~ ~ ~ ~             
}

Mientras que la Biblioteca Fuente

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().

arriba.jpg (2978 bytes) casa.jpg (31539 bytes)
Hosted by www.Geocities.ws

1