【问题标题】:Why are virtual methods considered early bound?为什么虚拟方法被认为是早期绑定的?
【发布时间】:2010-03-10 18:51:30
【问题描述】:

绑定的一个定义是,它是将函数名替换为内存地址的行为。

a) 因此,我假设早期绑定意味着函数调用在编译过程中被内存地址替换,而后期绑定这种替换发生在运行时?

b) 为什么虚拟方法也被认为是早期绑定(因此在编译时找到目标方法,并创建将调用此方法的代码)?据我所知,对于虚拟方法,对实际方法的调用仅在运行时解决,而不是编译时解决?!

感谢


编辑:

1)

A a=new A();
a.M();

据我所知,在编译时不知道在运行时将在堆上的哪个位置(因此在哪个内存地址)将实例 a 创建。 现在,通过早期绑定,函数调用在编译过程中被替换为内存地址。但是编译器如何用内存地址替换函数调用,如果它不知道在运行时将在堆上的哪个位置创建对象a(这里我假设方法a.M的地址也将在相同的内存位置作为a)?

2)

v-table 调用既不早绑定也不晚绑定。相反,函数指针表中有一个偏移量。偏移量在编译时是固定的,但是从哪个表中选择函数指针取决于对象的运行时类型(对象包含指向其 v-table 的隐藏指针),因此在运行时找到最终的函数地址。

但是假设 T 类型的对象是通过反射创建的(因此应用程序甚至不知道 T 类型的存在),那么在编译时如何存在该类型对象的入口点?

【问题讨论】:

  • 我不确定 C# 是否是一个正确的标签,因为 C# 至少在加载时间之前不会进行任何绑定。

标签: c#


【解决方案1】:

后期装订

使用后期绑定,您所拥有的只是方法的名称。在编译时,您无法知道该方法是否存在。这在 Ruby 或 Python 等语言中称为“鸭子类型”。

后期绑定很慢,因为您必须按名称查找函数。这也很危险,因为您没有受到轻微拼写错误的保护。

在版本 4 之前,除了显式调用反射 API 之外,C# 不支持后期绑定。

早期绑定

使用早期绑定时,您将针对实际方法进行编译。这种方法可以直接引用,也可以是V-table中的一个槽。无论哪种方式,您都可以保证不会抛出 MissingMethod 异常。

历史

Visual Basic 以支持早期绑定和后期绑定而闻名,但由于它的其他限制,它从未被视为真正的动态语言。同时,7 之前的版本(也称为 VB.NET)对强制早期绑定的支持非常差,因此也很难将其称为静态语言。

使用 .NET 4,可以说 C# 和 VB 都提供了静态和动态类型语言所期望的大多数功能。

有一次,Java 被错误地称为支持后期绑定,而事实上它只有早期绑定、OOP 样式的 V 表。多年来,这引起了很多混乱。

【讨论】:

  • 嗨,我已经编辑了我的第一篇文章......以防你找到时间
【解决方案2】:

当编译器在编译时知道确切的类型时,虚拟方法是早期绑定的。

如果编译器没有确切的类型,它将生成一个 vtable 查找样式的后期绑定。

【讨论】:

    【解决方案3】:

    正如 Joshua 所解释的那样,对虚拟方法的调用可能会被提前绑定(即编译器可以看到对象的确切类型,不会发生多态性),也可能是通过 v-table 进行的。

    C# 仅在您使用反射时进行后期绑定(在下一版本中,有一个新的“动态”关键字来请求后期绑定)。

    v-table 调用既不早绑定也不晚绑定。相反,函数指针表中有一个偏移量。偏移量在编译时是固定的,但是从哪个表中选择函数指针取决于对象的运行时类型(对象包含指向其 v-table 的隐藏指针),因此在运行时找到最终的函数地址。

    编辑以解决新问题:

    在 (1) 中,整个前提都是错误的。函数不会存储在“拥有”它们的对象附近的任何地方。事实上,整个程序只有一个函数副本,对象实例作为隐藏的“this”参数传递,因此函数知道正在寻址哪个实例。

    对于 (2),有两种可能性。一,函数调用是通过 MethodInfo 之类的反射完成的。这真是迟到了。第二,函数调用是通过调用者在编译时知道的接口或基类进行的,即使对象的总类型未知。在这种情况下使用 v-table 调用,因为 v-table 的布局由基类或接口决定,因此调用者知道它并可以预先确定到 v-table 的偏移量。

    【讨论】:

    • 嗨,我已经编辑了我的第一篇文章......以防你找到时间
    • Curios 命名约定。 vtable 查找是 C++ 中后期绑定的唯一形式。
    • 函数指针和 v-tables 一样晚,而且没有一个比动态链接晚(诚然,它不是标准化 C++ 语言的一部分,但仍然得到大量支持C++ 工具链)
    猜你喜欢
    • 2010-11-01
    • 1970-01-01
    • 2013-02-08
    • 1970-01-01
    • 2012-09-23
    • 1970-01-01
    • 2016-10-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多