Curso de C++ Builder


Ejemplo 2



Corresponde al final de la sección 5. En este ejemplo se muestra el POLIMORFISMO (Polimorfismo de clases y métodos virtuales).



EJEMPLO.CPP

//----------------------------------------------------------------------

#include <vcl.h> #pragma hdrstop USERES("Ejemplo2.res"); USEFORM("Ppal.cpp", PpalFrm); USEUNIT("ObjGraf.cpp"); //---------------------------------------------------------------------- WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) { try { Application->Initialize(); Application->CreateForm(__classid(TPpalFrm), &PpalFrm); Application->Run(); } catch (Exception &exception) { Application->ShowException(&exception); } return 0; } //----------------------------------------------------------------------


PPAL.H

//----------------------------------------------------------------------

#ifndef PpalH
#define PpalH

//----------------------------------------------------------------------

#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#include <ExtCtrls.hpp>

#include "ObjGraf.h"
#include <Buttons.hpp>

//----------------------------------------------------------------------

class TPpalFrm : public TForm
{
__published:	// IDE-managed Components
   TPaintBox *PaintBox;
   TBitBtn *BotonSalir;
   void __fastcall FormCreate(TObject *Sender);
   void __fastcall FormDestroy(TObject *Sender);
   void __fastcall PaintBoxPaint(TObject *Sender);
   void __fastcall BotonSalirClick(TObject *Sender);

private:	// User declarations

   TObjGraf **Objs;

public:		// User declarations
   __fastcall TPpalFrm(TComponent* Owner);
};

//----------------------------------------------------------------------
extern PACKAGE TPpalFrm *PpalFrm;
//----------------------------------------------------------------------

#endif



PPAL.CPP

//----------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Ppal.h"

//----------------------------------------------------------------------

#pragma package(smart_init)
#pragma resource "*.dfm"

TPpalFrm *PpalFrm;

//----------------------------------------------------------------------

__fastcall TPpalFrm::TPpalFrm(TComponent* Owner) : TForm(Owner)
{
}

 
//----------------------------------------------------------------------

void __fastcall TPpalFrm::FormCreate(TObject *Sender)
{
   Objs = new TObjGraf * [4];

   Objs[0] = new TCirculo  (PaintBox, clBlack,  100, 100, 30);
   Objs[1] = new TCuadrado (PaintBox, clRed,    200, 150, 45);
   Objs[2] = new TCirculo  (PaintBox, clGreen,  210,  40, 20);
   Objs[3] = new TPelota   (PaintBox, clYellow, 120,  70, 25);
}

//----------------------------------------------------------------------

void __fastcall TPpalFrm::FormDestroy(TObject *Sender)
{
   for (int i=0; i<4; i++)
      delete Objs[i];
   delete []Objs;
}

//----------------------------------------------------------------------

void __fastcall TPpalFrm::PaintBoxPaint(TObject *Sender)
{

   for (int i=0; i<4; i++)
      Objs[i]->Mostrar();
}

//----------------------------------------------------------------------

void __fastcall TPpalFrm::BotonSalirClick(TObject *Sender)
{
   Application->Terminate();    
}

//----------------------------------------------------------------------



OBJGRAF.H

//----------------------------------------------------------------------

#ifndef ObjGrafH
#define ObjGrafH

//*************************************************/
// Definicion de la clase base TObjGraf
//*************************************************/

class TObjGraf {

private:

   int FX;
   int FY;

   void SetX   (int _X);
   void SetY   (int _Y);
   virtual int GetAncho (void) = 0; // Metodo virtual puro
   virtual int GetAlto  (void) = 0; // Metodo virtual puro

protected:  

   TColor      FColor;
   TPaintBox   *PaintBox;

public:

   // Constructores de objetos TObjGraf

   TObjGraf (TPaintBox *_PaintBox, TColor _Color=clBlack, 
             int _X=0, int _Y=0);   TObjGraf (TObjGraf *ObjGraf);   

   // Otros metodos

   virtual void Mostrar (void) = 0; // Metodo virtual puro

   // NUEVAS FORMAS DE ACCESO AL DECLARAR PRIVATE LOS MIEMBROS FX y FY.

   __property int    X     =  {read=FX,      write=SetX  };
   __property int    Y     =  {read=FY,      write=SetY  };
   __property TColor Color =  {read=FColor,  write=FColor};
   __property int    Ancho =  {read=GetAncho             };
   __property int    Alto  =  {read=GetAlto              };

};

 
//*************************************************/
// Definicion de la clase derivada TCirculo.
// Deriva de la clase base TObjGraf
//*************************************************/

class TCirculo : public TObjGraf {

private:

   int FRadio;

   inline int GetAncho  (void) {return(FRadio*2);}
   inline int GetAlto   (void) {return(FRadio*2);}

public:

   // Constructores

   TCirculo (TPaintBox *_PaintBox, TColor _Color=clBlack,
             int _X=0, int _Y=0, int _Radio=1);

   // Otros metodos

   void Mostrar (void); // Instanciacion del metodo virtual puro de
                        // la clase TObjGraf

   __property int Radio =  {read=FRadio,  write=FRadio};

};

 
//*************************************************/
// Definicion de la clase derivada TPelota.
// TPelota deriva de la clase TCirculo, que a su
// vez deriva de la clase base TObjGraf
//*************************************************/

// Tipo definido por enumeracion para la direccion de TPelota
// La codificacion es:
/*

        NO    N    NE
         10   2    6
          \   |   /
           \  |  /
   O 8 ----      ---- 4 E
           /  |  \
          /   |   \
         9    1    5
        SO    S    SE
*/

enum TDireccion {S=1, N=2, E=4, O=8, SE=5, NE=6, SO=9, NO=10};

class TPelota: public TCirculo {

private:

   int FDirX;
   int FDirY;
   int FVelocidad;

   void        SetDireccion (TDireccion _Direccion);
   TDireccion  GetDireccion (void);

public :

   // Constructores

   TPelota (TPaintBox *_PaintBox, TColor _Color=clBlack,
             int _X=0, int _Y=0, int _Radio=1,
             TDireccion _Direccion=SE, int _Velocidad=5);

   // Otros metodos

   void Mostrar (void);
   void Borrar  (void);
   void Mover   (void);

   __property int        Velocidad = {read = FVelocidad,   write=FVelocidad};
   __property TDireccion Direccion = {read = GetDireccion, write=SetDireccion};

};

 
//*************************************************/
// Definicion de la clase derivada TCuadrado.
// Deriva de la clase base TObjGraf
//*************************************************/

class TCuadrado : public TObjGraf {private:   int FLado;

   inline int GetAncho  (void) {return(FLado);}
   inline int GetAlto   (void) {return(FLado);}

public:

   // Constructores

   TCuadrado (TPaintBox *_PaintBox, TColor _Color=clBlack,
             int _X=0, int _Y=0, int _Lado=1);

   // Otros metodos

   void Mostrar (void); // Instanciacion del metodo virtual puro de
                        // la clase TObjGraf

   __property int Lado =  {read=FLado,  write=FLado};

};

//----------------------------------------------------------------------

#endif


OBJGRAF.CPP


//----------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "ObjGraf.h"

//----------------------------------------------------------------------

#pragma package(smart_init)

 
/*****************************************************/
// Metodos asociados a la clase base TObjGraf
/*****************************************************/

// Constructores

TObjGraf :: TObjGraf (TPaintBox *_PaintBox, TColor _Color, 
                      int _X, int _Y)
{
   PaintBox = _PaintBox;
   FColor = _Color;
   FX = _X;
   FY = _Y;
}

TObjGraf :: TObjGraf (TObjGraf *ObjGraf)
{
   PaintBox = ObjGraf->PaintBox;
   FColor = ObjGraf->Color;
   FX = ObjGraf->FX;
   FY = ObjGraf->FY;
}

// Funciones de escritura de las propiedades virtuales X e Y

void TObjGraf :: SetX (int _X)
{
   if (_X < 0)
      FX = 0;
   else
      if (_X > (PaintBox->Width - Ancho))
         FX = PaintBox->Width - Ancho;
      else
         FX = _X;
}

void TObjGraf :: SetY (int _Y)
{
   if (_Y < 0)
      FY = 0;
   else
      if (_Y > (PaintBox->Height - Alto))
         FY = PaintBox->Height - Alto;
      else
         FY = _Y;
}

 
/*****************************************************/
// Metodos asociados a la clase derivada TCirculo.
// TCirculo deriva de la clase base TObjGraf.
/*****************************************************/

TCirculo :: TCirculo (TPaintBox *_PaintBox, TColor _Color,
                      int _X, int _Y, int _Radio) :
            TObjGraf (_PaintBox, _Color, _X, _Y)
{
   Radio = _Radio;
}

// Instanciacion del metodo virtual puro de la clase TObjGraf

void TCirculo :: Mostrar (void)
{
   PaintBox->Canvas->Pen->Color = Color;
   PaintBox->Canvas->Brush->Color = Color;
   PaintBox->Canvas->Ellipse(X, Y, X+Radio*2, Y+Radio*2);
}

 
/*****************************************************/
// Metodos asociados a la clase derivada TPelota.
// TPelota deriva de la clase TCirculo, que a su
// vez deriva de la clase base TObjGraf
/*****************************************************/

TPelota :: TPelota (TPaintBox *_PaintBox, TColor _Color,
             int _X, int _Y, int _Radio,
             TDireccion _Direccion, int _Velocidad) :
           TCirculo (_PaintBox, _Color, _X, _Y, _Radio)
{
   Direccion = _Direccion;
   Velocidad = _Velocidad;
}

// Instanciacion del metodo virtual puro de la clase TObjGraf

void TPelota :: Mostrar (void)
{
   PaintBox->Canvas->Pen->Color = clBlack;
   PaintBox->Canvas->Brush->Color = Color;
   PaintBox->Canvas->Ellipse(X, Y, X+Radio*2, Y+Radio*2);
}

// Otras funcione propias de TPelota

void TPelota :: Borrar (void)
{
   PaintBox->Canvas->Pen->Color = PaintBox->Color;
   PaintBox->Canvas->Brush->Color = PaintBox->Color;
   PaintBox->Canvas->Ellipse(X, Y, X+Radio*2, Y+Radio*2);
}

 
void TPelota :: Mover (void)
{
   Borrar ();
   X += FDirX * Velocidad;
   Y += FDirY * Velocidad;
   Mostrar ();
}

void TPelota :: SetDireccion (TDireccion _Dir)
{
   FDirY = (_Dir & 1) ? +1 : ((_Dir & 2) ? -1 : 0);
   FDirX = (_Dir & 4) ? +1 : ((_Dir & 8) ? -1 : 0);
}

TDireccion TPelota :: GetDireccion (void)
{
   TDireccion _Dir;

   _Dir = (TDireccion) ((FDirY == +1) ? 1 : ((FDirY == -1 ) ? 2 : 0));
   _Dir = (TDireccion) (_Dir +  (FDirX == +1) ? 4 : ((FDirX == -1 ) ? 8 :0));

   return (_Dir);
}

/*****************************************************/
// Metodos asociados a la clase derivada TCuadrado.
// TCuadrado deriva de la clase base TObjGraf.
/*****************************************************/

TCuadrado :: TCuadrado (TPaintBox *_PaintBox, TColor _Color,
                        int _X, int _Y, int _Lado) :
            TObjGraf (_PaintBox, _Color, _X, _Y)
{
   Lado = _Lado;
}

// Instanciacion del metodo virtual puro de la clase TObjGraf

void TCuadrado :: Mostrar (void)
{
   PaintBox->Canvas->Pen->Color = Color;
   PaintBox->Canvas->Brush->Color = Color;
   PaintBox->Canvas->Rectangle(X, Y, X+Lado, Y+Lado);
}



Atrás