Universidad de Costa Rica
|
|
En esta tarea programada usted hará lo propio, pero usará el lenguaje Turbo Pascal, en cualquiera de sus versiones, o el lenguaje C++. (Por supuesto, no puede usar plantillas si usa C++).
Implemente en su programa el equivalente del procedimiento
Swap()
de la Figura /24/ y también
implemente las clases RING
y MATRIX[T]
de la Figura /31/. Haga versiones de la clase
MATRIX[]
para los tipos INTEGER
y
BOOLEAN
. Si quiere obtener puntaje extra,
también implemente la clase STACK[T]
de la
Figura /35/.
Entregue una documentación suscinta junto a su programa, y muestre que funciona con sus datos de prueba. El objetivo de esta tarea es que usted experimente para que comprenda las ventajas de usar lenguaje que cuenta con parametrización y herencia.
Entregue su tarea en dos partes. Al final de la primera semana, debe entregar un listado que contenga la declaración de tipos los que usará en su programa, y al final de la segunda semana entregue su programa completo
InitDone.pas
se muestra como lograrlo en el contexto
de Turbo Pascal de 16 bits.
PROGRAM InitDone; { (c) 1998 adolfo@di-mare.com } TYPE TObj = OBJECT CONSTRUCTOR Init; DESTRUCTOR Done; END; { TObj } TYPE TFar_Pointer = RECORD CASE INTEGER OF 1:(ofs, seg: WORD; ); { véalo como 2 palabras } 2:(p : POINTER;); { véalo como puntero } END; CONSTRUCTOR TObj.Init; BEGIN WriteLn('TObj.Init: ', LONGINT(@SELF)); END; { TObj.Init } DESTRUCTOR TObj.Done; BEGIN WriteLn('TObj.Done: ', LONGINT(@SELF)); END; { TObj.Done } TYPE Pcnstr = PROCEDURE (vmtW: WORD; slf: POINTER); CONST N = 5; VAR i : INTEGER; pObj : TFar_Pointer; pVMT : POINTER; pInit, pDone: POINTER; BEGIN { InitDone } pVMT := TypeOf(TObj); { puntero a la VMT } pInit := @Tobj.Init; { puntero al constructor } pDone := @Tobj.Done; { puntero al destructor } System.GetMem(pObj.p, N*SizeOf(TObj)); FOR i := 1 TO N DO BEGIN { invoca al constructor en el objeto pObj^ } Pcnstr(pInit)(Ofs(pVMT^), pObj.p); INC(pObj.ofs, SizeOf(TObj)); END; FOR i := 1 TO N DO BEGIN DEC(pObj.ofs, SizeOf(TObj)); { invoca al destructor en el objeto pObj^ } Pcnstr(pDone)(0, pObj.p); END; System.FreeMem(pObj.p, N*SizeOf(TObj)); END. { InitDone } |
El tipo TObj
tiene su constructor
TObj.Init()
y su destructor TObj.Done()
.
Pcnstr(vmtW, slf)
es un tipo que sirve para
invocar al constructor TObj.Init()
por medio del
puntero pInit
(y también al destructor).
Parece extraño que el constructor de TObj
sea
un procedimiento que recibe dos argumentos, y no solamente uno
(SELF
). El primer argumento "vmtW
" es el
número que será almacenado en el campo VMT
(Virtual Method Table) del objeto
[BI88] (pp 104).
Al principio del programa se graba en los punteros
pVMT
, pInit
y pDone
las
direcciones de la VMT de TObj
, la dirección de
su constructor y la de su destructor. El tipo
TFar_Pointer
es un artilugio que permite incrementar
el puntero pObj
, que apunta a un vector, para
recorrer los N
elementos de tipo TObj
que contiene.
Luego, de un solo tirón, se adquiere suficiente memoria
dinámica para almacenar el vector de N
elementos, para lo que se invoca al procedimiento
System.GetMem()
. En los dos ciclos FOR
que siguen, se construye y destruye cada uno de los elmentos del
vector.
Para invocar al constructor, e inicializar cada objeto en el
vector, se usa una transferencia al tipo Pcnstr
, y
luego se agregan los argumentos que el constructor necesita:
Pcnstr(pInit)(Ofs(pVMT^), pObj.p);
El resultado de aplicarle la función Ofs()
al
puntero pVMT
es obtener el valor para el argumento
"vmtW
" que, contrario a lo que parece, no un puntero,
sino un número entero.
Para invocar al destructor se hace lo mismo, pero en lugar de
pasar el valor Ofs(pVMT^)
, como en el constructor,
hay que pasar el valor cero (0
). De esta manera se
evita que la memoria que SELF
ocupa sea retornada al
manejador de memoria dinámica, pues cuando el destructor es
invocado con un valor no nulo en el parámetro
"pVMT
" es porque se ha usado la sintáxis
extendida de System.DISPOSE()
:
System.DISPOSE(p, TObj.Done);
Al final, después de destruir todos los objetos del vector
(en el orden inverso de su creación), se devuelve toda la
memoria dinámica obtenida al principio invocando a
System.DISPOSE()
.
|
[BI88] | Borland International:
Turbo Pascal version 5.5
Object Oriented Programming Guide,
Borland International, California (U.S.A.), 1988.
|
[Mey86] | Meyer, Bertrand:
Genericity vs Inheritance,
OOPSLA'86 Conference Proceedings,
pp [391405],
Portland, Oregon, 1986.
|
Adolfo Di Mare <adolfo@di-mare.com>.
|