Link to home
Start Free TrialLog in
Avatar of Paer Toernell
Paer ToernellFlag for Thailand

asked on

Delphi Copy a Var integer to another var integer

I have quite normal parameter like:

Procedure Something(var test:integer);

In the form i have a global variabel (well global to that form) defied as:

  public
    { Public declarations }
   var gtest :integer;


Now i want to transfer the pointer from test to gtest.

gtest :=test; wont work. How should it be done?
Avatar of Manuel Lopez-Michelone
Manuel Lopez-Michelone
Flag of Mexico image

I don't understand your problem. When you define a procedure like this one:

Procedure Something(var test:integer);

the variable "test" is the formal name of the variable. Because you defined it as "var", you're saying to the compiler that the variable is passing by reference and not value. That means that when you use the procedure in any part of your program, you have to make the call:

Something(gtest);

(assuming this is a global variable for this procedure)...

if in your procedure you do something like this: test := test + 5;

then gtest will be whatever value has originally + 5. And the result finally will be gtest + 5.

If you define your procedure like this:

Procedure Something(test:integer);

without the var parameter, your variable with pass by value, and when you exit the procedure, your variable (for instance gtest) will not change the value at all.

regards,
Lopem
Avatar of Paer Toernell

ASKER

If we have a variable, say

myInt : integer;

Now I pass that to a procedure:

MyProcedure (myInt);

Defined as:

Procedure MyProcedure (var MyVarInt :integer);
Begin
   MyVarInt :=35;
End

Now i can change MyVarInt and myInt will change. Fine, normal, standard. No problem.

But if i want to copy the functionality of MyVarInt to another "var name:integer" how do i do that?
Put a form and a button... Define two global variables... Copy my code:

var
  Form1: TForm1;
  A, B : integer;

implementation

{$R *.dfm}

Procedure MyProcedureA (var MyVarInt :integer);
Begin
   MyVarInt :=35;
End;

Procedure MyProcedureB (MyVarInt :integer);
Begin
   MyVarInt :=35;
End;

procedure TForm1.Button1Click(Sender: TObject);
begin
  A := 10;
  ShowMessage('Variable before enter the procedure A = '+ inttostr(A));
  MyProcedureA(A);
  ShowMessage('Variable after enter the procedure A = '+ inttostr(A));

  B := 20;
  ShowMessage('Variable before enter the procedure B = '+ inttostr(B));
  MyProcedureB(B);
  ShowMessage('Variable after enter the procedure B = '+ inttostr(B));

end;

Run the program, you will see:

Variable A = 10 before MyProcedureA
Variable A changes to 35
Variable A = 35 as soon MyProcedureA ends.

Variable B =20 before MyProcedureB
Variable B changes to 35 inside the procedure
Variable B = 20 as soon MyProcedureB ends.

Notice MyProcedureA has a formal parameter: (var MyVarInt : integer);

MyVarInt is not the name of a variable, is the formal name of a variable you´re going to pass thru the procedure. Var means that it can change when the procedure finish. This is why  A starts with a 10 and finish with 35. If you dont use the var word, MyProcedureB will use the formal parameter MyVarInt to pass value to the procedure, but when the procedure finish, the variable B will return to the original value. This is why B = 20 and finish with B =20.

In fact, you dont have to create a MyVarInt variable. I repeat, this is just the formal name indicating that you´re going to pass a variable to the procedure.

For example, if you want B equals whatever A has after MyProcedureA, you can write:

A=10;
MyProcedureA(A);
B := A;

Please check in any Pascal manual the use of the var parameter in a procedure. Check passing a variable by reference or by value. I think this is what you´re not understanding.

Regards
Lopem
there is no functionality in an integer type
it just holds a number, that's the only functionality it has

if you want to add functionality, you need to look at OOP: Object Oriented Programming
and define your own type, with the functionality you want

for instance: an integer, with a status indicator of overloaded:

type
  TMyStatus = class(TPersistent)
  private
    fValue: integer;
  protected
    function GetOverLoaded: Boolean;
  public
    constructor Create(aValue: Integer = 0); virtual;
    procedure Assign(Source: TPersistent); override;
    property Value: Integer read fValue write fValue;
    property OverLoaded: Boolean read GetOverLoaded;
  end;

constructor TMyStatus.Create(aValue: Integer = 0);
begin
  inherited Create;
  fValue := aValue;
end;

function TMyStatus.GetOverLoaded: Boolean;
begin
  Result := fStatus > 100;
end;

procedure TMyStatus.Assign(Source: TPersistent); 
begin
  if Source is TMyStatus then 
  begin
    fValue := TMyStatus(Source).Value;
  end else 
    inherited Assign(Source); 
end;

Open in new window


for this sample, i used a TPersistent descendant, in which you need to override the Assign procedure
This allows copying properties from 1 object to another:

var 
  MyStatus1, MyStatus2: TMyStatus;

begin
  MyStatus1 := TMyStatus.Create(20);
  MyStatus2 := TMyStatus.Create;
  MyStatus2.Assign(MyStatus1); 
  ...

Open in new window


and if you want multiple variables to have the same value
then either, only use 1 variable

or use an observer pattern to indicate changes to listening objects
http://www.nickhodges.com/post/Delphi-and-the-Observer-Pattern.aspx
If you call

MyProcedure(gtest);

...value of outer variable gtest will be changed - because you define procedure that way...
Ok, let me rephrase my question. How do i copy a variable that don't hold a value but hold a reference to another variable so that variable also hold the same reference. I can do it with pointers or i can do i t with an object but that's not what i want.

So we have some forms that have an integer. Another object needs the reference to that integer. The form is not given, it variate and so can the name of the variable. To pass the reference into the the object is easy:

SomForm:

myobject.PassReference (MyInteger);

Open in new window


To receive the reference is easy:

procedure tmyobject.PassReference(var aRef : integer);
begin
end;

Open in new window


BUT the variable that holds the rererence (aRef ) will only work locally inside the procedure PassReference and vanish when PassReference goes out of scope . I need it to be available as long as the object exists.

Thats why i have a "global" variable defined in the object.

tmyobject= class(Tobject)

Public
  Var gMyRef : Integer;

Open in new window


So i need something like:

procedure tmyobject.PassReference(var aRef : integer);
begin
  gMyRef :=CopyReferenceOf(aRef );
end

Open in new window


So how do i copy/transfer the reference from aRef to gMyRef ?
ASKER CERTIFIED SOLUTION
Avatar of Sinisa Vuk
Sinisa Vuk
Flag of Croatia image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Yes, works. Thanx

unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;

type
  TForm1 = class(TForm)
    var
    Memo1: TMemo;
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
    var gINtRef : pInteger;
        gint    : Integer;
    Procedure SetRef(Var aint : integer);
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
      SetRef(gint);
      gINtRef^:=25;
      Memo1.Lines.Add(IntToStr(gint));
end;

procedure TForm1.SetRef(var aint: integer);
begin
     gINtRef:=@aint;
end;

end.