我不断听到有关早期和晚期绑定的信息,但我不了解它们是什么。我发现了以下我不理解的解释:


早期绑定是指在设计时将值分配给变量,而后期绑定是指在运行时将值分配给变量。 br />

有人可以定义两种绑定类型并进行比较吗?

评论

编译时间与运行时。

这是有关此主题的好书:en.wikibooks.org/wiki/Introduction_to_Programming_Languages/…

#1 楼

混乱中有两个主要概念:绑定和加载。它与DataBinding的概念混为一谈,后者处于中间位置,通常两者同时进行。在考虑了它之后,我将添加一个概念,以完成三连击,分派。 -时间;通常通过分配,但是还有其他手段可以强制类型;动态类型的语言将其称为基本功能,但是许多静态类型的语言都有一些实现后期绑定的方法

通常使用[特殊]动态类型,自省/反射,标志和编译器选项或通过虚拟实现借用和扩展动态分派的方法

早期绑定:类型通常是通过静态的声明性方法在运行时执行变量之前已知的类型,通常使用标准基本类型

函数

静态派发:编译时已知的特定函数或子例程;它是明确的,并由签名

实现为静态函数;没有方法可以具有相同的签名

动态调度:在编译时不是特定的函数或子例程;在执行期间由上下文确定。有两种不同的“动态调度”方法,以哪种上下文信息用于选择适当的功能实现来区分。

在单个[动态]分派中,仅使用实例的类型来确定适当的函数实现。在静态类型的语言中,实际上这意味着实例类型决定使用哪种方法实现,而与声明/分配变量时指示的引用类型无关。因为仅使用一种类型(对象实例的类型)来推断适当的实现,所以此方法称为“单一分派”。

还有多个[动态]分派,其中输入参数类型还有助于确定要调用的函数实现。因为实例的类型和参数的类型等多种类型都会影响选择哪种方法实现,所以这种方法被称为“多种调度”。

实现作为虚拟或抽象功能;其他线索包括重写,隐藏或隐藏的方法。

NB:方法重载是否涉及动态调度是特定于语言的。例如,在Java中,重载方法是静态分派的。允许对象处于本质上有效但已知为不完整的状态,并等待直到需要数据后再加载它;通常被发现对于加载大型数据集或等待外部资源特别有用。

通常是在构造函数或初始化调用期间,直到某些下游调用者要求查看内容时才有意不将集合或列表加载到复合对象中,从而实现这一目的该集合中的一个(例如get_value_at,get_all_as等)。变化包括加载有关集合的元信息(例如大小或键),但忽略实际数据;还为某些运行时提供了一种机制,为开发人员提供了一个相当安全有效的单例实现方案。

急于加载:对象初始化策略可立即执行所有值分配,以便在认为自己处于有效状态之前完成所有数据。尽快获取它们的已知数据,例如在构造函数调用或初始化期间

数据绑定:通常涉及在两个兼容的信息流之间创建活动链接或映射,以便对一个信息的更改反映回另一个反之亦然;为了兼容,它们通常必须具有通用的基本类型或接口

通常是为了在不同应用程序方面(例如,从视图模型到视图,控制器等),并讨论诸如源和目标,端点,绑定/解除绑定,更新和on_bind,on_property_change,on_explicit,on_out_of_scope




编辑事件提供这些事件如何发生的示例说明。特定的代码示例完全取决于实现/运行时/平台

评论


这个答案似乎过于面向对象的语言。

–杰克
2015年12月5日19:31

@Jack我不这么认为,我认为这是一个涵盖很多方面的优秀作品。

–laike9分钟
19/12/26在1:05

#2 楼

编译器在编译时确定的任何内容都可以称为EARLY / COMPILE TIME绑定,而在RUNTIME处确定的任何内容都称为LATE / RUNTIME绑定。 />方法重载和方法重载。

1)在方法重载中,对方法的方法调用由编译器决定,从某种意义上说,要调用哪个函数由编译器在编译时决定时间。因此,是早期绑定。

2)在方法重写中,在RUNTIME决定要调用哪个方法。因此,它被称为LATE BINDING。

试图使其保持简单易用。希望这会有所帮助。

#3 楼

后期绑定是在运行时评估行为时。当您确实想根据程序运行时所拥有的信息来确定如何采取措施时,这很有必要。在我看来,最清晰的示例是虚拟函数机制,特别是在C ++中。绑定,因此程序在运行时认为它只是指向a->f()类型变量的指针,而void A::f()实际上将调用A,因为看到a->g()是编译器的虚拟编译器会注入代码以查找要在运行时调用的正确函数的地址。

评论


“运行时”?您在谈论C ++。 C ++直接编译为机器代码,不需要运行时即可解析虚拟方法。

– tdammers
2013年6月1日下午6:16

@tdammers C ++实际上确实需要运行时库,尽管虚拟调用不需要。如果您仔细阅读,会发现此答案表明编译器“在运行时注入代码以查找正确函数的地址”。

–user7043
2013年6月1日8:50

好吧,但是“查找正确函数地址的代码”基本上只是一个与类型无关的两阶段指针取消引用,然后进行函数调用。没有涉及“思考”。它可靠工作的唯一原因是因为编译器在编译时进行了类型检查。在运行时,生成的代码将信任编译器完成类型检查作业。如果您使用不安全的强制类型转换(例如C风格的指针强制类型转换),则可以合法地将C ++对象视为错误类的对象,但是它们的vtable将被完全弄乱,并且代码只会中断。

– tdammers
13年6月1日,11:56

@tdammers我试图避开这种答案,因为它是编译器的实现细节,对于某些深奥的编译器来说可能是正确的,也可能不是。重要的是概念。

–任马可维奇
2013年6月1日13:34

@tdammers“运行时”是指“运行时的程序”。显然,C ++是不受管理的。但是,由于您向我展示了它会引起混乱,因此我将其改为完整的措词。

–任马可维奇
2013年6月1日13:36

#4 楼

如果您熟悉函数指针,这将是一个示例。
定义的函数可以说是早期绑定。
如果您使用函数指针则是后期绑定。

  int add(int x,int y)
  {
    return x+y;
  }
  int sub(int x,int y)
  {
      return x-y;
  }


    int main()
    {
     //get user choice
     int(*fp)(int,int);
     //if add
      fp=add;
     //else if sub
     fp=sub;
     cout<<fp(2,2);
    }


这里的函数add和sub是函数(其地址在编译时链接程序处绑定)

,但函数指针是后期绑定fp可以根据用户选择[在运行时]调用add或sub。

#5 楼

早期和晚期绑定仅在类型的上下文中有意义,而在您描述它的方式中则没有意义。几乎所有现代语言都是在所有值具有固定类型的意义上键入的。当我们查看动态类型和静态类型的语言时,会出现差异。在动态类型语言中,变量没有类型,因此它们可以引用任何类型的值,这意味着,当您在某个变量所引用的对象上调用方法时,确定该调用是否有效的唯一方法是:查找对象的类,看看该方法是否实际存在。这允许一些很酷的事情,例如在运行时向类添加新方法,因为实际的方法查找将推迟到最后一刻。大多数人都将这种状态称为后期绑定。严格来说,这不是真的,但让我们暂时假设。现在,如果您知道变量将仅引用特定类型的值,那么就没有理由找出方法调用在运行时是否有效,因为您可以在运行代码之前确定有效性。这被称为早期绑定。

演示红宝石中后期绑定的示例:

用Java之类的语言在运行时固定所有类型。

#6 楼

除了给您一个学术定义之外,我将尝试使用VBA的真实示例向您展示一些差异:

早期绑定: br />这需要在设计时将引用设置为“ Microsoft Scripting Runtime”组件。这样做的好处是,当您在FileSystemObject中输入错误或方法名称如GetSpecialFolder时,在编译时就已经收到错误消息。
这不需要事先设置引用,实例创建和类型确定将仅在运行时发生。当您尝试调用x的不存在的方法时,编译器不会在编译时抱怨,这仅在执行特定行时才会导致运行时错误。

因此,后期绑定的缺点是您在这里没有任何强类型检查。但这也是优点-假设您有一个组件,其中存在多个版本,并且每个较新的版本都提供一些其他功能。 (一个真实的示例是MS Office组件,例如Excel COM界面。)后期绑定使您可以编写可与所有版本一起使用的代码-您可以首先确定特定的组件版本,如果发现有仅旧版本可用,请避免执行不适用于该版本的函数调用。

#7 楼

后期绑定的最常见示例可能是解析Internet URL。它支持动态系统和大型系统,而无需尝试链接和绑定世界上任何一个站点,但另一方面,它在运行时确实会带来一些开销(DNS查找,IP路由要少得多)。

因此,在语言环境中,大多数绑定方式或多或少早于编译时或链接时。

每种都有成本和收益。

评论


您可以找到有关此绑定定义的参考吗?我还没有听说过将互联网地址解析为“绑定”,尽管由于绑定是解析名称的行为,所以我想有人认为早期/后期绑定的概念可以用于解析URI到互联网地址。但这不是一个常见的解释,早/晚绑定的概念早于计算机通常连接到Internet的时间。

–杰伊·埃尔斯顿(Jay Elston)
16年1月27日在15:44