I'm learning and there are things I don't understand. I was reading documentation about creating classes and constructors etc. But I can't understand how it works for what I need. I know that it is something basic and that I am not understanding, let me explain:
I need to create the Dog object from the class TDOG and use it independently as a container to make modifications to it, before assigning it back to the array containing a collection of dogs. But when assigning to the variable DOG , the object vector[i]
of the same class, to be able to edit it and later save it in the vector, it is as if any modification in the dog variable, immediately modifies the position of the vector.
type
Tperro = class
nombre : string;
raza : string;
end
var
vector : array [1..10] of TPerro;
implementation
procedure Tform1.cargarperros; //cargo los perros
begin
vector[1]:= TPerro.create
vector[1].nombre := 'Cubo';
vector[1].raza := 'caniche';
vector[2]:= TPerro.create;
vector[2].nombre :='Chopper';
vector[2].raza := 'labrador';
end;
procedure TForm1.edicion; // editar Perro, utilizando el objeto "PERRO" y no directamente desde el vector
var perro : TPerro;
begin
Perro := TPerro.create;
Perro := vector[1]; //asigno los datos de vector[1] a variable PERRO
Perro.name := 'Olmedo';
Showmessage('Nombre anterior ' + vector[1].name); //aca el nombre sale "olmedo" (cuando deberia salir "CUBO")
Showmessage('Nombre Nuevo ' + Perro.name); //aca sale nombre "olmedo"
vector[1] := Perro //aca vuelvo al vector, y le asigno las modificaciones en el (recipiente) PERRO.
end;
The showmessage
( which I use to show you what happens to me ) shows the same thing for both DOG , and for vector[1]
, when in fact I need that the vector that contains the collection of dogs, not be previously modified, without first verifying the DOG object , to which I make the modifications.
I remember that before using the class ( record ) I did not have these problems. But since I need to add methods to the TPerro class , I need to use it as an Object and not as a record. I don't know if you can add methods to the record class though . Still, I'm learning and need to understand how it works.
Any change you make to the DOG object is made immediately to the array position you previously assigned to it. ( PERRO := vector[1]
). Is there something I'm not understanding, or I don't know if I'm missing something, or I should declare the constructor method of the class with some kind of specification.
I hope to explain myself well.
In Delphi all objects are created in the memory area called heap (heap, in Spanish) and what you save, when you make an assignment to an object type variable is a reference , also known as a pointer to the memory address where it resides the object.
I recommend you read. If you don't have a good Pascal programming book, google, for example pascal pointers .
When you do this:
In the first line, you create a new instance of
TPerro
and assign to the variablePerro
the memory address where this new instance has been created. It is said that it nowPerro
points to the new instance ofTPerro
.In the second line, there is NOT an assignment of the values that are stored in the members of the dog pointed
vector[1]
to by this new dog instance, as you are assuming, but what happens is that now the variablePerro
points to the same address where it points tovector[1]
and any changes you make will be reflected in both (since they both point to the same object, which exists only once in memory.The basic test that is normally done to exemplify this is with two variables, for example:
Regardless of the memory size of an object, the variable used to access it will have a fixed size (4 bytes in 32-bit applications and 8 bytes in 64-bit applications).
It will show 40 if you build your app for 32-bit platforms and 80 if you build your app for 64-bit platforms.
If you want the new variable
Perro
to have a copy of the values contained in the object it points tovector[1]
, you have to go member by member, for example:If you look at my code, you'll notice that I'm careful to always release the objects I create. This prevents memory leaks (also known as memory leaks ), since there is no garbage collector in Delphi and it is the responsibility of the programmer to ensure that resources that are no longer used are returned to the system.
It only remains for me to explain the difference you see with the behavior of registers, and this is because registers are not pointers, but merely value containers that behave like other primitive data types, say an integer. When a local variable of type register is declared, the space for the entire structure is reserved on the stack (the stack) and not on the heap (as in the case of objects).
If you want to create records on the heap , you must use pointer operators, such as
^
and@
, in addition to theNew()
and functionsDispose()
to manage their memory, for example:This program, compiled for 32-bit, produces the output: