问题
As it pertains to Delphi...
When a variable is declare of a certain type, is it initialized to an OBJECT of that type? Or must the variable be assigned an expression which returns an object of that type?
I'm coming from a strong Java background. What I mean to ask is this... In Java, say you declare an instance variable of a user defined type named Orange. Which would look like this:
private Orange _fruit;
The variable _fruit still holds a reference to null until actually assigned an instance of the Orange class, like this:
_fruit = new Orange();
In Delphi if I declare a variable of type TForm, like this:
var
Form : TForm;
Is Form initlized to a TForm object? Or is it still nil?
I'm asking because I'm getting an error when trying to compile a small bit of code which is showen below:
Here is the Main unit:
unit Main;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils,
System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Second;
type
TForm1 = class(TForm)
ShowForm2: TButton;
procedure ShowForm2Click(Sender: TObject);
end;
var
Form1: TForm1;
SecondForm : TSecondForm;
implementation
{$R *.dfm}
procedure TForm1.ShowForm2Click(Sender: TObject);
begin
SecondForm.ShowModal;
end;
end.
and here is the Second unit:
unit Second;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs,
Vcl.StdCtrls;
type
TSecondForm = class(TForm)
Label1: TLabel;
end;
var
SecondForm: TSecondForm;
implementation
{$R *.dfm}
end.
The error I'm getting when I try to compile is exactly: "Access violation at address 005B17F9 in module 'Multiple.exe'. Read of address 00000000." I was thinking that it's because I don't somehow initialize the variable SecondForm in unit Main? However, I tried to place 'SecondForm.Create' in the ShowForm2Click procedure and I get the same error. Am I get this error because SecondForm is unassigned? Does it need to be initialized? Or is it?
Note: I'm three days new to Delphi. Please be considerate of that.
回答1:
also note that unit Second
and unit Main
both declare a global variable
SecondForm : TSecondForm;
In the case of the main unit your main unit will be hiding the SecondForm
variable declared in unit Second
(even though it lists it in the uses
clause). In the case of a Delphi VCL Forms application, if the SecondForm
is an auto-create form then the SecondForm
declared in unit Second
will not be nil
and will in fact already have an instance of TSecondForm
created and assigned to it, but this will be inaccessible by unit Main
because it declares a global of the same name (which, like all reference types, will be nil
until you do something with it).
In short, it's probably best not to declare a global SecondForm : TSecondForm
in unit Main
- call it something else or else use the global declared in unit Second
. If SecondForm
is an auto-create form (default behaviour) then the above code would work if you simply did not re-declare SecondForm
in unit Main
- if not you would still have to instantiate SecondForm
.
VCL Forms are automatically auto-create forms unless you otherwise specify. Check menu:
Project > Options > Forms
to see or change which forms will automatically have an instance assigned to their IDE-generated globals.
回答2:
SecondForm.Create
is the wrong syntax. Constructors are special in Delphi. You can think of them more or less like class methods. The way you invoke them is like this:
variable := ClassType.Create(arguments);
While it is possible to invoke a constructor like an instance method (variable.Create
) this is for one specific use case and should not be done in general code. The reason to call a constructor on an object and not a type is if you're already inside a constructor for that object. (ie. if you have more than one constructor on the object and one of them calls another one, or to initialize the ancestor class's members by calling a constructor on the parent class with inherited Create(arguments);
)
What you did, calling a constructor on an object when not inside another constructor for that object, should probably raise a compiler warning, if not an error, but unfortunately it doesn't.
回答3:
Yes, SecondForm
is nil
until you assign it.
Try something like this:
procedure TForm1.ShowForm2Click(Sender: TObject);
begin
with TSecondForm.Create(nil) do try
ShowModal;
finally
Free;
end;
end;
来源:https://stackoverflow.com/questions/16598931/understanding-delphi-variable-declarations-initializations