Pascal - 分配给函数调用

发布于 2025-01-09 14:43:29 字数 1039 浏览 2 评论 0原文

我正在查看 CodeGear C++ Builder 头文件的源代码。在 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 类型的实例并返回该实例通过参考实例。在我的调用中,InstanceClass 不是 TForm,因此后半部分并不重要。

我对 TComponent(Reference) := Instance; 感到困惑。 从语法上看,这里发生了什么?这是通过引用进行赋值吗?这是分配一个新的 TComponent 并为实例化器参数 Reference 分配值吗? TComponent() 是类型转换吗?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

绻影浮沉 2025-01-16 14:43:29
  1. 过程的签名中,形式参数reference并不指示数据类型,而是被声明为var可用参数。
  2. 无类型参数在 Pascal 中不合法,但在方言中允许,例如 GNU Pascal 和 FreePascal。
    在那里,这样的变量参数接受任何数据的实际参数类型。
    编译器不会强制/限制允许的数据类型,但它必须是可寻址的(即不允许使用文字)。
  3. dataTypeName(expression) 确实是类型转换(在 Pascal 中也是非法的,但某些方言允许)。
    具体来说,dataTypeName(variableName) 是一个变量类型转换
    它将被视为 variableName 属于指定的数据类型。
    这是必要的,因为在这种特殊情况下,reference 没有关联的数据类型。
    没有关联的数据类型意味着,在如何访问相关变量方面没有商定的规则(即任何读/写访问都是不可能的)。
  4. 该过程可能创建一个TComponentClass的实例,即。 e.参数 InstanceClass 的数据类型,但您应该真正阅读 NewInstance 方法的文档。
    我只能告诉你它是 TComponent 的后代,否则类型转换为不相关的类几乎没有意义。
  1. In the procedure’s signature the formal parameter reference does not indicate a data type, but is declared as a variable parameter.
  2. Typeless parameters are not legal in Pascal, but permitted in dialects such as GNU Pascal and FreePascal.
    There, such variable parameters accept actual parameters of any data type.
    The compiler will not enforce/restrict permissible data types, but it must be addressable (i. e. literals are not permitted).
  3. 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).
  4. The procedure probably creates an instance of 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.
孤独难免 2025-01-16 14:43:29

Reference 参数是无类型的 var 参数。在C++术语中,它大致相当于void*,即任何变量的地址都可以绑定到它。该代码将 Reference 类型转换为 TComponent*&TComponent** 的等效项,然后分配 Instance< /code> 变量(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));

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));
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文