Reputation: 564
I am looking at the source code for CodeGear C++ Builder header files. In Source/vcl/forms.pas
I find the following lines of code:
procedure TApplication.CreateForm(InstanceClass: TComponentClass; var Reference);
var
Instance: TComponent;
begin
Instance := TComponent(InstanceClass.NewInstance); // 메타클래스 이용하여, 인스턴스화
TComponent(Reference) := Instance;
try
Instance.Create(Self); // 폼 생성
except
TComponent(Reference) := nil;
raise;
end;
if (FMainForm = nil) and (Instance is TForm) then
begin
TForm(Instance).HandleNeeded; // 윈도우핸들을 생성
FMainForm := TForm(Instance);
end;
end;
Contextually, what I think is happening is that this procedure creates an instance of type InstanceClass
and returns that instance through Reference
. In my call, InstanceClass
is not TForm
, so the second half doesn't matter.
I am confused by TComponent(Reference) := Instance;
. Syntactically, what is happening here? Is this assignment by reference? Is this assigning a new TComponent
with the instantiator argument Reference
being assigned the value? Is TComponent()
a type casting?
Upvotes: 1
Views: 194
Reputation: 595305
The Reference
parameter is an untyped var
parameter. In C++ terms, it is roughly equivalent to void*
, ie the address of any variable can be bound to it. The code is type-casting the Reference
to the equivalent of TComponent*&
or TComponent**
and then assigning the Instance
variable (a TComponent*
pointer) to the caller's passed variable.
The code is roughly equivalent to the following in C++ (except that metaclasses and virtual constructors don't exist in C++, so this code is actually not usable in C++):
void __fastcall TApplication::CreateForm(TComponentClass* InstanceClass, void* Reference)
{
// this just allocates a block of memory of the required size...
TComponent* Instance = static_cast<TComponent*>(InstanceClass->NewInstance());
// *static_cast<TComponent**>(Reference) = Instance;
reinterpret_cast<TComponent*&>(Reference) = Instance;
try
{
// This is calling the class' virtual constructor
// on the allocated memory. In C++, this would be
// similar to calling 'placement-new' if the class
// type was known statically here...
// new(Instance) InstanceClass->ClassType()(this);
Instance->Create(this);
}
catch (...)
{
// *static_cast<TComponent**>(Reference) = NULL;
reinterpret_cast<TComponent*&>(Reference) = NULL;
throw;
}
if ((!FMainForm) && (dynamic_cast<TForm*>(Instance) != NULL))
{
static_cast<TForm*>(Instance)->HandleNeeded();
FMainForm = static_cast<TForm*>(Instance);
}
}
// Application.CreateForm(TForm, Form1);
Application->CreateForm(__classid(TForm), reinterpret_cast<void*>(&Form1));
Upvotes: 0
Reputation: 1554
procedure
’s signature the formal parameter reference
does not indicate a data type, but is declared as a var
iable parameter.dataTypeName(expression)
is indeed a typecast (also illegal in Pascal, but allowed by some dialects).
Specifically, dataTypeName(variableName)
is a variable typecast.
It will be treated as if variableName
was of the named data type.
This is necessary, because in this particular case reference
has no associated data type.
No associated data type means, there is no agreed rule in how to access the variable in question (i. e. any read/write access is impossible).TComponentClass
, i. e. the data type of the parameter InstanceClass
, but there you should really read the documentation of the NewInstance
method.
I can only tell you it’s a descendant of TComponent
otherwise it hardly makes sense to typecast to an unrelated class.Upvotes: 2