【问题标题】:O'Reilly's "Objective-C Pocket Reference" claims C++ doesn't support Dynamic Dispatch, is this true?O'Reilly 的“Objective-C Pocket Reference”声称 C++ 不支持动态调度,这是真的吗?
【发布时间】:2012-01-02 20:36:45
【问题描述】:

第 4 页上写着:

Objective-C 动态决定——在运行时——通过搜索接收者的类和父类来处理消息的代码。 (Objective-C 运行时缓存搜索结果以获得更好的性能。)相比之下,C++ 编译器在编译时静态构造调度表。

我在 StackOverflow 和 Wikipedia 上阅读了很多内容,我只想说我完全不知道 C++ 是否支持动态调度(有人说这是动态绑定的一种实现)。

谁能弄清楚动态调度、动态绑定以及 C++ 是否支持其中之一或两者之间的区别?我不是 C++ 或 Objective-C 专家,我来自 Java、Python 和 PHP 世界。

【问题讨论】:

  • 我不认为这本书是说 C++ 不支持动态调度。我认为这是说在 C++ 中,调度表(用于动态调度)是在编译时构建的(即“静态”)。这是真的,至少对于许多常见的 C++ 实现来说是这样。不过,我对 Objective-C 一无所知,因此我无法将其与 Objective-C 所做的相提并论。
  • 我想这取决于你如何定义这些。我想大多数人会说 C++ 具有“动态调度”,尽管大多数实现不需要进行任何运行时搜索来实现这一点。
  • 我添加了objective-c 标签。讨论可能会受益于objective-c 中的知识渊博的人

标签: c++ objective-c dynamic-binding dynamic-dispatch


【解决方案1】:

本书中提到的动态调度可能是在 C++ 上下文中通常提到的不同的动态调度:

  • C++ 支持虚函数形式的动态调度。相应的名称和参数在编译时确实是已知的,尽管调用的实际函数取决于对象的动态类型。
  • 我不是 Objective C 专家,但我的理解是,您可以在运行时动态地将函数添加到单个对象,这些对象在被调用时会被查找。 C++ 不支持这种动态调度。

【讨论】:

    【解决方案2】:

    C++ 确实支持通过虚拟成员函数进行动态调度。

    我不认为这本书有其他说法。它指出“C++ 编译器在编译时静态地构造一个调度表”。确实如此:用于实现动态调度的调度表(“vtable”)是在编译时构建的,至少在大多数常见的 C++ 实现中是这样。

    【讨论】:

      【解决方案3】:

      您的标题与您的问题不同。

      书中的陈述是正确的:C++ 虚拟调度是在运行时执行的,但是调度表是在编译时生成的。但是,这与说 C++ 不支持“动态调度”不同。虚函数是动态调度的一种形式,但在术语“动态调度”下有许多级别的事物。

      【讨论】:

      • 这本书似乎明确指出 C++ 确实支持“动态调度”,这本书似乎将其定义为能够在运行时确定调度哪个方法通过搜索接收者及其父类来响应消息。我认为混淆的地方可能是这样一个事实,即在 Objective-C 中,消息的接收者类可能在应用程序的运行生命周期中的某个时刻没有发送响应的方法,但 稍后 在应用程序的同一运行中,可能已向该目标类添加了一个新方法,允许其响应。
      • 问题似乎是“动态”一词本身的使用被超载了:-P。既然C++是静态构造调度表的,那它怎么支持动态调度……调度表是静态的。 Objective-C 允许在运行时修改调度表。我错过了什么吗?
      • 除非你在谈论你没有引用的书的一部分,否则书本身从不使用术语“动态调度”。它非常清楚地解释了 ObjectiveC 和 C++ 的行为,但它从不使用您询问的术语。
      • 至于C++如何有“动态调度”,这完全取决于你如何定义这个术语。由于您和本书都没有定义它,因此可以使用各种定义中的任何一种来定义它。 C++ 允许通过多态性将派生类用作基类。由于一段代码不能静态地知道虚函数调用将调用哪个方法(它可以调用基类实现或任何派生类实现),它是一个动态称呼。因此:动态调度。
      【解决方案4】:

      如果“动态调度”的意思是“在运行时更改为调用给定对象的方法调用的函数”,那么是的:C++ 在语言级别没有结构化的本地机制来执行此操作(这意味着在运行时更改 v-table 指针,甚至是 v-table 内的函数指针:可以通过强制实现特定的结构来实现,但可能会伤害孩子 :-) 将其视为“色情编码”!)

      但是 C++ 有一个基于类继承和虚函数的“动态调度”。 您可以通过将对象实现为子对象的聚合、为给定接口实现它们自己的变体(实质上是“行为模式”)以及在需要时更改子对象来实现最可能的动态调度。

      【讨论】:

        【解决方案5】:

        基本上,通过使用关键字“virtual”,C++ 是“部分”动态的。我们通常将此功能称为“后期方法绑定”,它决定了在运行时调用的具体方法。

        然而,OC 通过其强大的运行时系统是“纯粹的”动态的(不像 javascript 那样纯粹)。您可以在运行时添加方法和 ivars,更不用说在运行时选择正确的方法来调用。我们通常将此功能称为“动态消息分发”。

        如您所见,从方法调用的角度来看,它们的功能几乎相同。详细的方法搜索过程不同(c++ 查找虚拟表,oc 在其类的方法列表中试试运气),但它们都获得了运行时的灵活性。

        【讨论】:

          【解决方案6】:

          C++ 是否支持通过virtual functions 进行动态调度。

          但是,它不(本机)支持double dispatch,这是一个根据对象的运行时类型方法参数的运行时类型来确定要调用的方法的系统。

          【讨论】:

            猜你喜欢
            • 2010-11-20
            • 2010-09-29
            • 1970-01-01
            • 2012-06-26
            • 2012-05-18
            • 1970-01-01
            • 2011-10-31
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多