This section is not intended to give a completetheory will be presented only OOP concepts necessary for proper programming inC + + Builder.
OOP is a programming paradigm that is based onthe concepts of object and class . First, define what we mean by object class:
Purpose: | An autonomous entity with a specific and well defined functionality. |
Class: | Specification of the characteristics of a set of objects. An object is an instance of a class. |
The concepts presented in this section areillustrated using an example that will be completed gradually as new conceptsare introduced. Moreover, this sameexample is used in the sections on exceptionhandling and programming with threads . So, prepare the way in creating a project:
· Create a project ( File | New | Application )
· Change the name of the form ( Name = PpalFrm ). Place a PaintBox page component System is called PaintBox with Align = alTop . Leave space below PaintBox to place a button.
· Placing a bevel of width 4 and aligned at the top ( Align = alTop) . The idea is to delimit the bottom of PaintBox .
· Place a button bit that allows program execution end. The button will be centered horizontally at thebottom of the form.
· Save the form's code Ppal.cpp and the project as Ejemplo.bpr .
· A unit ( File | New | Unit ). Saving it ObjGraf.cpp
When you create a unit so created, in fact, two files, one withextension . cpp and one with extension . h . Thus, we have two files: ObjGraf.h , statements containing the classes with which we work, and ObjGraf.cpp , containing the definition (implementation ofmethods) of these.
In ObjGraf.h :
//-------------------------------------------------
# Ifndef ObjGrafH
# define ObjGrafH
/ /Definition of class TObjGraf
class TObjGraf {};
# Endif
//-------------------------------------------------
Note that the class name is preceded by a T , and, while not mandatory, but is highly recommended because itis a convention of C + + Builder that almost all class names are preceded by T .
Very Important: Using the example above we could only define theclass, but not create any object.
Thereare four basic principles that any system must incorporate object-oriented,which are outlined in Figure 1.
Figure1 . Pillars of OOP.
It has been said that a class is only a specification . To use the functionalitycontained therein, must instantiate classes.
1. Declaration creation .
An object can be instantiated in a simple,declaring a variable of type class.
In Ppal.h :
# Include "ObjGraf.h"
In Ppal.cpp :
Clicking twice in OnCreate of the tab Events editor objects PpalFrm :
//------------------------------------------------ -
void __fastcall TPpalFrm: FormCreate (TObject * Sender)
{
TObjGraf ObjGraf1 ();
TObjGraf ObjGraf2;
}
//------------------------------------------------ -
Although this form is possible, and broadly used in programming C + + classic in C + + Builder is used very rarely. This is so for two reasons, mainly: 1. The length of the objects usually go beyond a simple function or block. Because the focus of the event-driven programming, it is normal that an object is created in an event handler and destroyed in another. 2. You can not use this type of creation with the VCL. Therefore, we do not use it. |
2. Dynamic Creation
Is the standard way of creating objects in C + + Builder , and is performed byoperator new .
When we use new to instantiate an object using a variable referencing or pointing to the newly createdobject (otherwise it would be totally inaccessible). In short, it requiresadvance notice of a pointer to the type of objects to be created.
In Ppal.cpp :
TObjGraf * ObjGraf / / Global Variable.
/ /ObjGraf is a pointer to objects of type TObjGraf
//------------------------------------------------ -
void __fastcall TPpalFrm: FormCreate (TObject * Sender)
{
ObjGraf = newTObjGraf;
}
//------------------------------------------------ -
The way to set the initial state or destroy thecomponents of an object is discussed in the section dedicated to Builders and Destroyers
Caution: When using this form ofclass instantiation is the sole responsibility of the programmer to correcttheir destruction.
3. Destruction of objects
When an object ceases to be useful must be eliminated. Thus, the application retrieves the resources(memory) that the object was captured when created.
The destruction of objects created at runtime with new operator is done using the delete .
In Ppal.cpp :
Double-clicking on OnDestroy the tab Events editor objects PpalFrm :
//-------------------------------------------------
void __fastcall TPpalFrm: FormDestroy (TObject * Sender)
{
delete ObjGraf;
}
//-------------------------------------------------
Inclassical programming language ( C ,for example) there are data and procedures that act on that data. There is no apparent relationship between dataand procedures (functions) and this relationship is more or less accu accordingto the professionalism of the controller.
Inan object we can distinguish two distinct aspects:
· State -----------> Properties
· Behavior ---> Methods
InOOP the data and manage the procedures that relate explicitly and"encapsulated" in an object. The specification of object properties andmethods of access is the declaration of the class that you instantiate theobject.
Figure2 outlines the properties and methods that will be associated to objects ofclass TObjGraf :
Figure 2 . Properties and methods of class objects TObjGraf .
Thedeclaration of properties and methods of class objects TObjGraf is performed as follows:
In ObjGraf.h :
//------------------------------------------------ -
class {TObjGraf
public:
int X / / Properties
int Y;
TColor Color;
TPaintBox *PaintBox;
void Display ( void) / / Methods
};
//------------------------------------------------ -
Access to Members of an Object
Toaccess the members of an object using typical operators access to members: theoperator . fordirect reference to the object and the operator -> to access through a pointer.As we always createobjects with new ,and referenced by a pointer, the access operator will use the operator ->
In Ppal.cpp :
//------------------------------------------------ -
void __fastcall TPpalFrm: FormCreate (TObject * Sender)
{
...
int Valory;
...
ObjGraf-> x = 5;
Valory = ObjGraf-> Y;
ObjGraf-> Show () / /Equivalent to (* Obj). Display ();
}
//------------------------------------------------ -
Note: Theellipsis is not a reserved word in C + +, simply mean that you miss a lot ofcode, either because it is irrelevant or because it has been discussed above.
Theyare methods for establishing the initial and final state of an object. Constructors can define a set of arbitraryarguments, but can not return anything. And the destroyers can not receive or return avalue.
Theconstructor must be called by the class, and the destroyer class name precededby the character ~
Aconstructor is executed when you create a new object: 1) by declaration, or 2)when it is created dynamically with operator new . Adestructor is executed when the object ceases to exist: 1) because its scopeends, or 2) when explicitly frees the operator delete .
In ObjGraf.h :
class {TObjGraf
...
/ / Constructor objectsTObjGraf
TObjGraf (TPaintBox* _PaintBox, TColor _color = clBlack ,
int _X= 0, int y = 0);
/ / The destructor is: ~TObjGraf ( void );
};
In ObjGraf.cpp :
TObjGraf: TObjGraf ( TPaintBox * _PaintBox, TColor_color,
int_X, int _Y)
{
PaintBox = _PaintBox;
Color = _color;
X = _X;
Y = _Y;
}
In Ppal.cpp :
void __fastcall TPpalFrm: FormCreate (TObject * Sender)
{
ObjGraf = newTObjGraf (PaintBox, clRed, 10, 10);
}
Important: No need to write a destructor unless the objectrequires additional dynamic memory. If so, the task of the destructor will basicallybe free dynamic memory occupied by the object being to destroy.
When a class inheritsfrom another, the derivedclass incorporates all membersof the baseclass as well as their own.
Inheritance is a veryimportant tool in many aspects of application development:
· Organization design.
· Reusability of classes (proper or not).
· Improved maintenance.
Based on the class TObjGraf are going to build two new classes, TCirculo and TCuadrado , which derive from TObjGraf . This means that objectsof these classes have associated properties and methods of the base class, TObjGraf , besides their own. Figure 5.3 outlines the inheritance mechanismfor new classes and new properties that are associated with objects of thederived classes.
Figure3 . Classes TCirculo and TCuadrado inherit properties and methods of the class TObjGraf 4
In ObjGraf.h :
//************************************************ * /
/ / Definition of the derived class TCirculo
/ / Base class derives TObjGraf
//************************************************ * /
class TCirculo: public {TObjGraf
public:
int Radio / /exclusive property TCirculo
};
//************************************************ * /
/ / Definition of the derived class TCuadrado.
/ / Base class derives TObjGraf
//************************************************ * /
class TCuadrado: public {TObjGraf
public :
int side, / /exclusive property TCuadrado
};
Before the base classname must put public , this is because C + + inheritance also allows private . But this is rarely used, so we assume that thereis only the public .
Constructors and destructors of a class not are automaticallyinherited by his descendants. We will create its own child classes constructors and destructors. It is possible, however,use the base class constructors, but it must be indicated explicitly . If so, you must know:
1. constructors anddestructors to base classes are invoked automatically by the constructors ofderived classes, and
2. that derived classesdestructors are invoked before the base classes.
To determine which parameters are called the constructors of baseclasses, use the initialization list .
In ObjGraf.h :
//************************************************ * /
/ / Definition of the derived class TCirculo
/ / Base class derives TObjGraf
//************************************************ * /
class TCirculo: public {TObjGraf
public :
int Radio / /exclusive property TCirculo
/ / Constructor Method
TCirculo ( TPaintBox* _PaintBox, TColor _color = clBlack ,
int _X= 0, int y = 0, int _Radio = 1);
};
//************************************************ * /
/ / Definition of the derived class TCuadrado.
/ / Base class derives TObjGraf
//************************************************ * /
class TCuadrado: public {TObjGraf
public :
int side, / /exclusive property TCuadrado
/ / Constructor Method
TCuadrado ( TPaintBox* _PaintBox, TColor _color = clBlack ,
int_X = 0, int y = 0, int _Lado = 1);
};
In ObjGraf.cpp :
TCirculo: TCirculo ( TPaintBox * _PaintBox, TColor_color,
int_x, int _y, int _Radio):
TObjGraf(_PaintBox, _color, _X, _Y)
{
Radius = _Radio;
}
TCuadrado: TCuadrado ( TPaintBox * _PaintBox, TColor_color,
int_x, int _y, int _Lado):
TObjGraf(_PaintBox, _color, _X, _Y)
{
Side = _Lado;
}
Abstract class : a class that is not fully specified (it has not implementedmethods), therefore you can not create instances of the same . An abstract class isused to serve as the base class to other classes. In C + + terminology issaid that an abstract class is one that has at least one pure virtual method .
· Virtual forces derived classes to implement this method.
· Pure: can not create instances of that class.
In ObjGraf.h :
class {TObjGraf
public:
...
/ / Other methods
virtual voidDisplay ( void ) = 0 / / pure virtual method
};
class TCirculo: public {TObjGraf
public:
...
/ / Instantiation of purevirtual method of the class TObjGraf
void Display ( void);
};
class TCuadrado: public {TObjGraf
public:
...
/ / Instantiation of purevirtual method of the class TObjGraf
void Display ( void);
};
In ObjGraf.cpp :
void TCirculo:: Show ( void )
{
PaintBox-> Canvas->Pen-> Color = Color;
PaintBox-> Canvas->Brush-> Color = Color;
PaintBox-> Canvas->Ellipse (X, Y, X + radius * 2, Y + radius * 2);
}
...
void TCuadrado:: Show ( void )
{
PaintBox-> Canvas->Pen-> Color = Color;
PaintBox-> Canvas->Brush-> Color = Color;
PaintBox-> Canvas->Rectangle (X, Y, X + Side, Y + side);
}
Why specify the method Show in TObjGraf as pure virtual, ratherthan omit it? Basically we can consider two reasons to use pure virtual methods:
1. To force descendantclasses to implement them. In this way we are sure that all descendants abstract classes TObjGraf have the method andsafely be invoked.
2. To avoid that you caninstantiate the abstract class.
In this state, if we try to run the program, we will get an error:can not instantiate an abstract class. Why?: Remember that Ppal.cpp associated with the eventmanager OnCreate of the form is written as follows:
//------------------------------------------------ -
void __fastcall TPpalFrm: FormCreate (TObject * Sender)
{
ObjGraf = newTObjGraf (PaintBox, clRed, 10, 10);
};
//------------------------------------------------ -
So then we daughters class objects:
1. First, in Ppal.cpp have to clear the globalvariable declaration:
2. ObjGraf TObjGraf * / /Global Variable.
and instead be declared four pointers toreference two objects of type TCirculo and two others to reference objects of type TCuadrado :
/ / Pointers to objectsof derived classes.
Cir1 TCirculo *, * Cir2;
Cuad1 TCuadrado *, *Cuad2;
3. Second, modify thefunction FormCreate to create two objects of each class referenced by the pointersdeclared above:
4. //------------------------------------------------ -
5.
6. void __fastcall TPpalFrm: FormCreate (TObject * Sender)
7. {
8. Cir1 = newTCirculo (PaintBox, clBlack , 100, 100, 30);
9. Cir2 = newTCirculo (PaintBox, clGreen , 210, 40, 20);
10. Cuad1 = newTCuadrado (PaintBox, clRed , 200, 150, 45);
11. Cuad2 = newTCuadrado (PaintBox, clYellow , 120, 70, 25);
12.};
13.
14.//------------------------------------------------ -
15. Finally, we modify thefunction FormDestroy to delete objects created:
16.//------------------------------------------------ -
17.
18.void __fastcall TPpalFrm: FormDestroy (TObject * Sender)
19.{
20. delete Cir1;
21. delete Cir2;
22. delete Cuad1;
23. delete Cuad2;
24.}
25.
26.//------------------------------------------------ -
Now, running the program is created and destroyed objects ofderived classes, but not displayed in the window. Why? At no time has beencalled the method Show () associated with each object. To display objects, justtell the manager associated with the event OnPaint component PaintBox :
//------------------------------------------------ -
void __fastcall TPpalFrm: PaintBoxPaint (TObject * Sender)
{
Cir1-> Show ();
Cir2-> Show ();
Cuad1-> Show ();
Cuad2-> Show ();
}
//------------------------------------------------ -
The result is shown in Figure 4:
4 Figure 4 . Project outcome Ejemplo.bpr .
Exercise:
Build the kind TTriangulo and modify the project to provide a resultsimilar to Figure 5.
Figure 5 . Project outcome Ejemplo.bpr class objects showing TTriangulo .
Multiple inheritance is the fact that a derived class is generatedfrom multiple base classes.
Example:
At a car dealership might consider the following class hierarchy:
class TProducto {
long price;
...
};
class TVehiculo {
int NumRuedas;
...
};
class TCocheEnVenta: public TProducto, public TVehiculo {
...
};
Note that the objects of the class TCocheEnVenta classes derived from TProducto and TVehiculo .
There are two ways for a class to take advantage of the benefitsof another, one is the inheritance, and the other is a class containing anobject of another class.
Neither possibility is better than the other, in each particularcase must be studied which is the best option.
For example, if we wanted to design a class ( TMarco ) comprising a frame(represented by a square and a circle), we may choose different strategies incarrying out:
· That inherits from TCirculo and TCuadrado .
· That inherits from TObjGraf and contains an object of class TCirculo and a TCuadrado .
· That inherits from TCirculo and contains an object of class TCuadrado .
· That inherits from TCuadrado and contains an object of class TCirculo .
Isthe concealment of details irrelevant or not to be displayed. We can distinguish two aspects in a class fromthe point of view of abstraction:
· Interface: what you see / use an object externally.
· Implementation: how it carries out its mission.
Inshort: we want to know what offers us an object, but not how it performs.
In C + + you can specify access to class members using thefollowing access specifiers:
· public : class interface.
· private : Implementation of the class.
· protected : Implementation of the family.
These specifications do not modify or access the form andbehavior, only control from where you can use the class members:
· public : from anywhere.
· private , from the methods of the class.
· protected : from the methods of the class and from the methods of derivedclasses.
In ObjGraf.h :
//************************************************ * /
/ / Definition of the base class TObjGraf
//************************************************ * /
class {TObjGraf
private: / / can only accessobjects of this class.
int X,
int Y;
protected: / / can access theobjects of this class and its descendants.
TColor Color;
TPaintBox *PaintBox;
public: / / can use them all.
/ / Constructor objectsTObjGraf
TObjGraf (TPaintBox* _PaintBox, TColor _color = clBlack ,
int _X= 0, int y = 0);
/ / Other methods
virtual voidDisplay ( void ) = 0 / / pure virtual method
};
Changing the way the classes TCirculo and TCuadrado for their properties Radio and Lado are protected and publicmethods:
//************************************************ * /
/ / Definition of the derived class TCirculo.
/ / Base class derives TObjGraf
//************************************************ * /
class TCirculo: public {TObjGraf
protected: / / can access theobjects of this class and its descendants.
int Radio;
public:
/ / Constructor Method
TCirculo ( TPaintBox* _PaintBox, TColor _color = clBlack ,
int _X= 0, int y = 0, int _Radio = 1);
void Display ( void) / / instantiation of pure virtual method
/ /Class TObjGraf
};
//************************************************ * /
/ / Definition of the derived class TCuadrado.
/ / Base class derives TObjGraf
//************************************************ * /
class TCuadrado: public {TObjGraf
protected: / / can access theobjects of this class and its descendants.
int side;
public:
/ / Constructor Method
TCuadrado ( TPaintBox* _PaintBox, TColor _color = clBlack ,
int_X = 0, int y = 0, int _Lado = 1);
void Display ( void) / / instantiation of pure virtual method
/ /Class TObjGraf
};
Thus, if in Ppal.cpp we wrote:
//------------------------------------------------ -
void __fastcall TPpalFrm: FormCreate (TObject * Sender)
{
...
Cir1-> Show (); / /Can.
Cir1-> X = 10 / / Youcan not because X is private.
}
//------------------------------------------------ -
In fact these three access specifiers are those of C + + , but C + + Builder there is an additionalone, which is the __published . We will not give much importance to this switch, because their useis restricted to the IDE . When we see a section class __published means that the memberscontained therein are maintained automatically by the IDE and we should notchange anything in that section, because otherwise the results can beunpredictable.
It is a good programming technique does not allow public access tothe properties of an object, because if this happens it could jeopardize theintegrity of the object. So how can change the state of an object from the outside?
1. Offering methods(public) to be responsible for modifying the properties (private) want. Thus are the methodsthat access the properties and the user of the class is only accessible throughthem. This is the classic technique that is used in C + +
2. Through the methods andproperties of "virtual". This technique is unique to C + + Builder and described in thenext section.
Propertiesare defined by methods of reading ( read ) and / or writing ( write ). Theyare called virtual because, really, no. The user of the class uses these properties asif they were real properties and ultimately result in the call to a method oraccess to real property. Moreover,if a virtual property is used for reading (eg the right side of an assignment)results in a different action if that virtual popiedad used for writing. The action that occurs when virtual property isread is specified, syntactically, by the reserved word read while writing when used to specify to write . Hereis an example.
In ObjGraf.h :
//************************************************ * /
/ / Definition of the base class TObjGraf
//************************************************ * /
class {TObjGraf
private: / / can only accessobjects of this class.
int FX / / NOTE:It has been renamed to
int FY / / X andY members to FX and FY.
void setX ( int _X);
void SetY ( int _Y)
virtual intGetAncho ( void ) = 0 / / pure virtual method
virtual intGetAlto ( void ) = 0 / / pure virtual method
protected: / / can access theobjects of this class and descendants.
TColor FColor / / NOTE: Color Changed byFColor
TPaintBox *PaintBox;
public: / / can use them all.
/ / Constructor objectsTObjGraf
TObjGraf (TPaintBox* _PaintBox, TColor _color = clBlack ,
int _X= 0, int y = 0);
/ / Other methods
virtual voidDisplay ( void ) = 0 / / pure virtual method
/ / NEW FORMS OF ACCESSTO VIRTUAL PROPERTIES.
__property int X = { read = FX, write = setX};
__property int Y = { read = FY, write = SetY};
__property TColorColor = { read = FColor, write= FColor};
__property int width = { read = GetAncho };
__property int height = { read = GetAlto};
};
Comments:
· Note that the "old" property X (resp. Y ) is now called FX (resp. FY ). Inaddition, a virtual property (public) called X (resp. Y ). Theseproperties are declared in the class TObjGraf which means that their descendants alsoinherited.
If Ppal.cpp thisproperty will be used for reading:
Cir1 CX = int-> X;
In fact it is as if we were
Cir1 CX = int-> FX;
because when you read access to the property(virtual) X actuallybecomes the owner (real) FX . The last statement, however, an error povocarÃabecause FX isprivate property.
If you used this property to write:
Cir1-> X = 100;
In fact it is as if we were
Cir1-> setX (100);
because when you write access to the property(virtual) X actuallycalls the setX () . The last statement, however, fails becausepovocarÃa setX () isa private method. The"redirect" writing method setX () can check the validity of the parameter andcorrect, if any, value: an extra edge.
· The virtual property Color isassociated with the same access method for reading and writing: Returns or typedirectly in real property FColor .
· Finally, note that virtual properties Width and Height donot have associated access methods for writing.
Aswe have added two new methods to the base class TObjGraf ( GetAncho () and GetAlto () ) and they need to have declared pure virtualinstances in derived classes:
//************************************************ * /
/ / Definition of the derived class TCirculo.
/ / Base class derives TObjGraf
//************************************************ * /
class TCirculo: public {TObjGraf
protected: / / can access theobjects of this class and descendants.
int Radio;
inline intGetAncho ( void ) { return (radius * 2);}
inline intGetAlto ( void ) { return (radius * 2);}
public:
/ / Constructor Method
TCirculo ( TPaintBox* _PaintBox, TColor _color = clBlack ,
int _X= 0, int y = 0, int _Radio = 1);
void Display ( void) / / instantiation of pure virtual method
/ /The class TObjGraf
};
//************************************************ * /
/ / Definition of the derived class TCuadrado.
/ / Base class derives TObjGraf
//************************************************ * /
class TCuadrado: public {TObjGraf
protected: / / can access theobjects of this class and descendants.
int side;
inline intGetAncho ( void ) { return (side);}
inline intGetAlto ( void ) { return (side);}
public:
/ / Constructor Method
TCuadrado ( TPaintBox* _PaintBox, TColor _color = clBlack ,
int_X = 0, int y = 0, int _Lado = 1);
void Display ( void) / / instantiation of pure virtual method
/ /The class TObjGraf
};
Now,we add (in ObjGraf.cpp )functions write virtualproperties X and Y :
/ / Write functions virtualproperties X and Y
void TObjGraf:: setX ( int _X)
{
if (_x <0) / /negative coordinates
FX = 0, / / Set the left margin
else
if (_x>(PaintBox-> Width - width)) / / Too High
FX = PaintBox->Width - Width, / / Set theright margin
else
FX = _X / / Correct: writing withoutchanging
}
void TObjGraf: SetY ( int _Y)
{
if (_Y <0) / /negative coordinates
FY = 0, / / Set the top margin
else
if (_Y>(PaintBox-> Height - High)) / / Too High
FY = PaintBox->Height - High; / / Set the bottom margin
else
FY = _Y / /Correct: writing without changing
}
Important: Change the class constructor TObjGraf because you can not call pure virtual methods virtual propertyfrom a base class constructor .
Inthis case, you can not call pure virtual methods ( GetAncho () and GetAlto () )virtual properties ( Width and Height ) from the base class constructor TObjGraf .
In ObjGraf.cpp :
TObjGraf: TObjGraf ( TPaintBox * _PaintBox,
TColor_color, int _X, int _Y)
{
PaintBox = _PaintBox;
_color FColor = / / VERYIMPORTANT: These three lines have changed:
FX = _X, / / Can not call pure virtual methods
FY = _Y / / (GetAncho,GetAlto) to set the value of a
/ /Virtual property (height, width) from a
/ /Base class constructor.
}
The result the same as the one shown in Figure 4.
Experimenting with virtual properties.
1. The builders do not verify coordinates.
Graphic objects ( Cir1 , Cir2 , Cuad1 and Cuad2 ) are created with theirbuilders, who ultimately call the base class constructor to set the values ofreal properties FX, FY , FColor and PaintBox . The consequence is that if you create a circle,for example, incorrect coordinates not corrected because as thebase class constructor can not use virtual property X for writing the method is not used setX () .
Asa demonstration, in the function FormCreate () of Ppal.cpp change the line:
Cir1 = new TCirculo (PaintBox, clBlack, 100,100, 30);
by:
Cir1 = new TCirculo (PaintBox, clBlack,-100, 100, 30);
Note that the black circle is not shown.
2. Reading / writing through virtual properties.
Modify the function PaintBoxPaint () of Ppal.cpp adding this line at thebeginning:
if (Cir1-> X <0) Cir1-> X = 100;
Note that virtual property X is used for reading and writing. The above line sets the coordinate X to the value 100.
An illuminating example is to change the previous line:
if (Cir1-> X <0) Cir1-> X = -200;
Note that the black circle has the value 0 in the coordinate X : This value is set through the input method setX () .
Isto show different behaviors depending on the situation. It can take three forms:
· Functions :overload.
· Classes :It is usually referred to the concept of polymorphism.
· Dynamic Link :virtual methods.
Itoccurs when a class has two methods with same name but different parameterlist. Thecompiler treats them as two different methods and apply each of them in theappropriate situation.
Forexample, you could overload the class constructor TObjGraf adding a new copy constructor :
In ObjGraf.h :
TObjGraf (TObjGraf * ObjGraf);
In ObjGraf.cpp :
TObjGraf: TObjGraf (TObjGraf * ObjGraf)
{
PaintBox = ObjGraf->PaintBox;
FColor = ObjGraf->Color;
ObjGraf-FX => FX;
FY = ObjGraf-> FY;
}
Aclass can behave as either of its predecessors (in the allocation for example). Because we have variables (pointers) that cancontain objects of different classes, the compiler does not know what type ofobject is actually pointing to the variable (at compile time) so no link delayrun-time.
The dynamic link link is to delay calling a method (function) atruntime.
Toillustrate polymorphism, create a new class, TPelota , resulting from the class TCirculo . Aball (an object of type TPelota ,to be precise) is a circle that has the ability to move. To implement the movement of a ball we need toincorporate new properties and methods proper to the class TPelota . However,at this time we want to show the polymorphism, which got through the method Show () associated with the class TPelota . Before,modify the declaration of the method Show () class TCirculo to force their offspring to implement your ownmethod Show () :simply enter the method Show () class TCirculo is virtual.
In ObjGraf.h :
//************************************************ * /
/ / Definition of the derived class TCirculo.
/ / Base class derives TObjGraf
//************************************************ * /
class TCirculo: public {TObjGraf
private:
...
public:
...
/ / Now the method Show() is declared virtual, though not pure:
/ / 1) Being virtual: anyclass that derives from TCirculo must
/ / Have their own methodShow (),
/ / 2) Not to be pure:You can call this method TCirculo objects.
virtual voidDisplay ( void );
...
};
Nowwe focus on the new class TPelota . Previously, for convenience and clarity, wedefine a type of enumeration to the direction of motion:
In ObjGraf.h :
/ / Type defined by enumeration for TPelota address. Coding:
/ *
NO N NE
10 2 6
\ | /
O 8 --- 4 --- * E
/ | \
9 1 5
S SE SW
* /
enum {TDireccion S = 1, N = 2, E = 4, O = 8, SE = 5, NE = 6, OS = 9,NO = 10};
Theclass declaration TPelota bemade in ObjGraf.h :
//************************************************ * /
/ / Definition of the derived class TPelota.
/ / TPelota TCirculo derived class, which in
/ / Turn derives from the base class TObjGraf
//************************************************ * /
class TPelota: public {TCirculo
private:
int FDirX / / Dirin X
int FDirY / / Diron the Y axis
int FVelocidad // speed of movement
void SetDireccion (TDireccion _Direccion)
TDireccion GetDireccion ( void );
public:
/ / Constructors
TPelota ( TPaintBox
/ / Other methods
void Display ( void)
void Clear ( void)
void Move ( void);
__property int speed = { read = FVelocidad,
write= FVelocidad};
__property TDireccionAddress = { read = GetDireccion,
write= SetDireccion};
};
Theimplementation of the methods of the class TPelota be made in ObjGraf.cpp :
/************************************************* ****/
/ / Method associated with the derived class TPelota.
/ / TPelota TCirculo derived class, which in
/ / Turn derives from the base class TObjGraf
/************************************************* ****/
TPelota: TPelota ( TPaintBox * _PaintBox, TColor_color, int _x,
int _y,int _Radio, TDireccion _Direccion, int _Velocidad):
TCirculo(_PaintBox, _color, _X, _Y, _Radio)
{
Address = _Direccion;
Speed = _Velocidad;
}
/ / Instantiation of pure virtual method of the class TObjGraf
/ / And virtual TCirculo.
void TPelota:: Show ( void )
{
PaintBox-> Canvas-> Pen -> Color = clBlack / / Note the difference
PaintBox-> Canvas-> Brush -> Color = Color;
PaintBox-> Canvas-> Ellipse (X, Y, X + radius * 2, Y + radius * 2);
}
/ / Other functions of TPelota
void TPelota:: Delete ( void )
{
PaintBox-> Canvas-> Pen -> Color = PaintBox-> Color;
PaintBox-> Canvas-> Brush -> Color = PaintBox-> Color;
PaintBox-> Canvas-> Ellipse (X, Y, X + radius * 2, Y + radius * 2);
}
void TPelota:: Move ( void )
{
Delete ();
X + = FDirX * Speed;
Y + = FDirY * Speed;
Show ();
}
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);
}
Finally,to illustrate the polymorphism we will build on the existence of differentmethods with the same name: Show () ,which cause different actions depending on the type of objects to which theyapply.
Wewill dynamically create four objects of different classes. These objects will be referenced (usingpointers) from a vector of objects of type TObjGraf * . Polymorphismis going to manifest invoking the function Display () for each of these objects.
In Ppal.cpp declare the global variable:
** TObjGraf Objs;
whichis interpreted as: Objs isa pointer to a memory area that contains pointers to objects of type TObjGraf .
Thus,in Ppal.cpp :
//----------------------------------------------------------------------
void __fastcall TPpalFrm: FormCreate (TObject * Sender)
{
Objs = new TObjGraf *[4];
Objs [0] = newTCirculo (PaintBox, clBlack, 100, 100, 30);
Objs [1] = newTCuadrado (PaintBox, clRed, 200, 150, 45);
Objs [2] = newTCirculo (PaintBox, clGreen, 210, 40, 20);
Objs [3] = newTPelota (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] -> Show ()/ / Polymorphism
}
//----------------------------------------------------------------------
The result is shown in Figure 6:
0 comments:
Post a Comment