Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-pascal / 2006-07

Another Delphi mode question :) -- classes as parameter

7 messages · 4 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Alexandre Leclerc

I tried the following:

procedure ThisAndThat(bitmap: TBitmap);
begin
  if not Assigned(bitmap) then
    bitmap := TBitmap.Create;
end;
function Test: boolean;
var
  bitmap: TBitmap;
begin
  bitmap := nil;
  ThisAndThat(bitmap);
  Result := Assigned(bitmap);
  bitmap.Free;
end;

In Delphi a class is always treated as a 'var' when passed in a function since a class is a pointer to actual data; logical but confusing when begining in Delphi. So in Delphi Test() would return true. I made a function like this in Lazarus and I see that it's not working. This behave as a local copy of the class! Now in FPC I changed the procedure for:

    procedure ThisAndThat(var bitmap: TBitmap);

and this is working.

The question: I guess this is an other delphi mode thing? Is there a page with all these Delphi mode / FPC differences? I'll check the wiki right after.

I prefer the behaviour of FPC because it is consistent, but is it really a copy a of class?!?. Since my background, I'll have to check all my functions that have classes in parameters to make sure this is working as expected.

Best regards.

Alexandre Leclerc
Michael Van Canneyt
to Alexandre Leclerc
Alexandre Leclerc wrote 22 lines
I tried the following: procedure ThisAndThat(bitmap: TBitmap); begin if not Assigned(bitmap) then bitmap := TBitmap.Create; end; function Test: boolean; var bitmap: TBitmap; begin bitmap := nil; ThisAndThat(bitmap); Result := Assigned(bitmap); bitmap.Free; end; In Delphi a class is always treated as a 'var' when passed in a function since a class is a pointer to actual data; logical but confusing when begining in Delphi. So in Delphi Test() would return true.

Ahem.

Have you tried that ? Because it is manifestly NOT true:

-----------------------------------------------------------------------
procedure TForm2.DoTest(S : TStrings);
begin
   S:=TStringList.Create;
end;
procedure TForm2.WisaButton1Click(Sender: TObject);
Var
   S : TSTrings;
begin
   S:=Nil;
   DoTest(S);
   If S=Nil then
     ShowMessage('S still nil')
   else
     ShowMessage('S assigned');
end;
-----------------------------------------------------------------------

Shows 'S still nil'.

What is more, it gives a warning for the dotest method:

[Hint] frmmain.pas(44): Value assigned to 'S' never used

What IS true is that you can change the properties of S, even if it is passed by value or as const. But the pointer S cannot be changed.

So FPC is perfectly compliant.

Michael.

Felipe Monteiro de Carvalho
to Alexandre Leclerc: I tried the following: procedure ThisAndThat(bitmap: TBitmap); begin if not…
Alexandre Leclerc wrote
In Delphi a class is always treated as a 'var' when passed in a function since a class is a pointer to actual data;

No, not really. It is always passed as a pointer, but here you want to change the pointer and not the contents of the class. So when you put a class as var you are passing a pointer to the pointer.

Felipe Monteiro de Carvalho
Alexandre Leclerc
to Michael Van Canneyt: Ahem. Have you tried that ? Because it is manifestly NOT true:…

2006/7/12, Michael Van Canneyt :

Ahem. Have you tried that ? Because it is manifestly NOT true:

Ah! I learnd something today! You are completly correct:

What IS true is that you can change the properties of S, even if it is passed by value or as const. But the pointer S cannot be changed.

I desired to change the pointer; manifestly I have to pass it as var.

What is more, it gives a warning for the dotest method: [Hint] frmmain.pas(44): Value assigned to 'S' never used

There are so many hints that I'm not reading them anymore. (I found that sometimes hints where kind of useless... For example, the implementation of a form event OnKeyDown will generate a hint "Hint: Parameter "Shift" not used" if I do not use this one parameter... but I don't care about that and can't do nothing about it. This is not a hint, this is obivious; this makes noise in the messages. So when you have many functions/procedures/events like this, you have a plethora of "useless" hint. So I do not check them anymore... It take too much time to parse them all and get the relevent one.)

(By the way, can GetLongOpts have the parameter 'out' instead of 'var Longind: Longint' this would avoid another hint about the variable not initialized (it is useless to init the var since this is out only)... unless 'out' does not allow 'nil').

So FPC is perfectly compliant.

Yes, thank you for this. Best regards.

Alexandre Leclerc
Alexandre Leclerc
to Felipe Monteiro de Carvalho: No, not really. It is always passed as a pointer, but here you want to change the pointer…

2006/7/12, Felipe Monteiro de Carvalho :

Show quoted text 7 lines
On 7/12/06, Alexandre Leclerc wrote: > In Delphi a class is always treated as a 'var' when passed in a > function since a class is a pointer to actual data; No, not really. It is always passed as a pointer, but here you want to change the pointer and not the contents of the class. So when you put a class as var you are passing a pointer to the pointer.

Yes, it is really an error from myself. Thanks.

Alexandre Leclerc
memsom
to Alexandre Leclerc: 2006/7/12, Michael Van Canneyt : Ah! I learnd something today! You are completly correct:…
> What IS true is that you can change the properties of S, even if it is > passed by value or as const. But the pointer S cannot be changed. I desired to change the pointer; manifestly I have to pass it as var.

Be aware that if you do this, you will lose the ability to pass any class that descends from the param type. Var params have to be the smae type exactly. The Delphi compiler will halt on an error if the exact type isn't used (though, thinking about it, the "Strict var params" switch might loosen this in Delphi..)

Best advice: Don't use var params for initialization. Either return the instance of the class - and raise an exception if there is an error, or use 'out' params, as it makes your intention clearer.

M

Alexandre Leclerc
to memsom

2006/7/13, memsom :

Show quoted text 5 lines
Be aware that if you do this, you will lose the ability to pass any class that descends from the param type. Var params have to be the smae type exactly. The Delphi compiler will halt on an error if the exact type isn't used (though, thinking about it, the "Strict var params" switch might loosen this in Delphi..)

Thank you for the information. I did not know that.

Best advice: Don't use var params for initialization. Either return the instance of the class - and raise an exception if there is an error, or use 'out' params, as it makes your intention clearer.

It made me revise my code and I'm able to do what you suggest. This is a better approach that I usually take, but I took this code from an example on VirtualTreeView and in order to test quickly I simply took it like that. Now I'll remake the procedure into a function.

Best regards.

Alexandre Leclerc