Pascal - 函数调用赋值
Pascal - Assignment to Function Call
我正在查看 CodeGear C++ Builder 头文件的 source code。在 Source/vcl/forms.pas
中,我找到以下代码行:
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;
从上下文来看,我认为正在发生的事情是此过程创建了一个 InstanceClass
类型的实例,并且 returns 该实例通过 Reference
。在我的调用中,InstanceClass
不是 TForm
,所以后半部分无关紧要。
我被TComponent(Reference) := Instance;
搞糊涂了。 从句法上讲,这里发生了什么?这个赋值是引用吗?这是在为实例化器参数 Reference
分配值时分配新的 TComponent
吗? TComponent()
是类型转换吗?
- 在
procedure
的签名中,形式参数reference
不表示数据类型,而是声明为var
iable参数。
- 无类型参数在 Pascal 中是不合法的,但在 GNU Pascal 和 FreePascal 等方言中是允许的。
在那里,这样的 variable parameters 接受 any 数据类型的实际参数。
编译器不会 enforce/restrict 允许的数据类型,但它必须是 可寻址的 (即不允许文字)。
dataTypeName(expression)
确实是类型转换(在 Pascal 中也是非法的,但某些方言允许)。
具体来说,dataTypeName(variableName)
是一个 variable typecast。
它将被视为 variableName
是指定的数据类型。
这是必要的,因为在这种特殊情况下 reference
没有关联的数据类型。
没有关联的数据类型意味着,在如何访问相关变量方面没有一致的规则(即任何 read/write 访问都是不可能的)。
- 过程 可能 创建了
TComponentClass
的一个实例,即。 e.参数 InstanceClass
的数据类型,但您真的应该阅读 NewInstance
方法的文档。
我只能告诉你它是 TComponent
的后代,否则将类型转换为不相关的 class. 几乎没有意义
Reference
参数是一个未类型化的 var
参数。在C++术语中,它大致等价于void*
,即任何变量的地址都可以绑定到它。代码是 type-casting Reference
相当于 TComponent*&
或 TComponent**
,然后将 Instance
变量(TComponent*
指针)分配给调用方传递的变量。
这段代码大致等同于C++中的以下代码(除了C++中不存在元类和虚构造函数,所以这段代码实际上在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));
我正在查看 CodeGear C++ Builder 头文件的 source code。在 Source/vcl/forms.pas
中,我找到以下代码行:
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;
从上下文来看,我认为正在发生的事情是此过程创建了一个 InstanceClass
类型的实例,并且 returns 该实例通过 Reference
。在我的调用中,InstanceClass
不是 TForm
,所以后半部分无关紧要。
我被TComponent(Reference) := Instance;
搞糊涂了。 从句法上讲,这里发生了什么?这个赋值是引用吗?这是在为实例化器参数 Reference
分配值时分配新的 TComponent
吗? TComponent()
是类型转换吗?
- 在
procedure
的签名中,形式参数reference
不表示数据类型,而是声明为var
iable参数。 - 无类型参数在 Pascal 中是不合法的,但在 GNU Pascal 和 FreePascal 等方言中是允许的。 在那里,这样的 variable parameters 接受 any 数据类型的实际参数。 编译器不会 enforce/restrict 允许的数据类型,但它必须是 可寻址的 (即不允许文字)。
dataTypeName(expression)
确实是类型转换(在 Pascal 中也是非法的,但某些方言允许)。 具体来说,dataTypeName(variableName)
是一个 variable typecast。 它将被视为variableName
是指定的数据类型。 这是必要的,因为在这种特殊情况下reference
没有关联的数据类型。 没有关联的数据类型意味着,在如何访问相关变量方面没有一致的规则(即任何 read/write 访问都是不可能的)。- 过程 可能 创建了
TComponentClass
的一个实例,即。 e.参数InstanceClass
的数据类型,但您真的应该阅读NewInstance
方法的文档。 我只能告诉你它是TComponent
的后代,否则将类型转换为不相关的 class. 几乎没有意义
Reference
参数是一个未类型化的 var
参数。在C++术语中,它大致等价于void*
,即任何变量的地址都可以绑定到它。代码是 type-casting Reference
相当于 TComponent*&
或 TComponent**
,然后将 Instance
变量(TComponent*
指针)分配给调用方传递的变量。
这段代码大致等同于C++中的以下代码(除了C++中不存在元类和虚构造函数,所以这段代码实际上在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));