【问题标题】:What's the relationship between C++ template and duck typing?C++模板和鸭子类型有什么关系?
【发布时间】:2011-10-18 21:27:13
【问题描述】:

对我来说,C++ 模板使用了鸭子类型的思想,对吗?是不是表示模板类或方法中引用的所有泛型类型都是鸭子类型?

【问题讨论】:

    标签: c++ templates duck-typing


    【解决方案1】:

    对我来说,C++ 模板是鸭子类型的编译时版本。 编译器将编译例如上课,只要你的鸭子 具有所有需要的类型,它将实例化一个类。

    如果某些地方不正确(例如缺少复制构造函数),则编译失败。 当您使用 非鸭型。在这里它会在运行时发生。

    【讨论】:

    • 嗯..我从鸭子打字的理解是,你试图找出类型。这意味着您遇到一个动态对象并且您不确定类型。在 c++ 模板中,您必须确定类型才能实例化它。
    • -1。 Duck 类型不一定意味着动态类型或运行时检查。编译时鸭子类型仍然是鸭子类型。
    • C++ 模板最初是基于令牌重放的。这仍然显示在它的鸭类属性中。
    【解决方案2】:

    鸭子打字的意思是,“如果它像鸭子一样嘎嘎叫,像鸭子一样走路,那么它就是一只鸭子”。它在计算机科学中没有正式的定义供我们比较 C++。

    当然,C++ 与(例如)Python 不同,但它们都有隐式定义接口的概念。用作 Python 函数参数的对象所需的接口是函数对其执行的任何操作。用作 C++ 模板参数的类型所需的接口是模板对该类型的对象所做的任何事情。这就是相似性,也是评估 C++ 模板的依据。

    此外,由于模板参数推导,在 C++ 中你可以尝试传递任何旧对象,编译器会判断它是否可以实例化函数模板。

    一个不同之处在于,在 C++ 中,如果参数不嘎嘎作响,则编译器对象。在 Python 中,只有运行时对象(并且仅当函数被实际调用时,如果代码中有条件)。这是对象/类型所要求的接口性质的差异——在 C++ 中,模板要求特定表达式有效,或者不需要。在 Python 中,必要的有效表达式可以依赖于早期必要表达式的运行时值。因此,在 Python 中,您可以请求一个可以大声或安静地嘎嘎叫的物体,如果它大声嘎嘎叫,它也需要走路。在 C++ 中,你可以通过条件 dynamic_cast 来做到这一点,如果卷是编译时常量,你可以使用模板特化,但你不能使用静态类型来说鸭子只需要在 @987654322 时行走@ 返回loud。当然,在 Python 中,所需的接口可能并不是真正“必需的”——如果方法不存在,则行为是抛出异常,如果发生这种情况,可能会记录并保证调用者的行为。

    取决于你是否定义“鸭子类型”,以便这种差异意味着 C++ 没有它。

    【讨论】:

      【解决方案3】:

      对我来说,C++ 模板使用了鸭子类型的思想,对吗?

      不,C++ 模板用于实现通用代码。也就是说,如果您的代码可以使用多种类型,则不必为每种类型复制它。 std::vectorstd::list 之类的东西就是这种行为的明显例子。 C++ 模板have been abused 做其他事情,但通用性是初衷。

      是指模板类或方法中引用的所有泛型类型吗 是鸭子类型的吗?

      不,它们只是“普通”类型,就像 C++ 中的所有其他类型一样。在模板实际实例化之前,它们是未知的。

      然而,模板可以用来实现一些类似鸭式的东西。迭代器就是一个例子。考虑这个函数:

      template<class InputIterator, class OutputIterator>
          OutputIterator copy(InputIterator first, InputIterator last,
                              OutputIterator result)
      {
          while (first!=last) *result++ = *first++;
          return result;
      }
      

      请注意,copy 函数可以接受任何类型的参数,同时它还实现了不等式运算符、取消引用运算符和后缀递增运算符。这可能与您在 C++ 中的鸭子类型一样接近。

      【讨论】:

      • 从我对鸭式打字的有限理解来看,您对复制功能的描述听起来就像它使用鸭式打字一样。 C++ 模板没有“实现”的鸭子类型的特征究竟是什么?
      • @aioobe:据我所知,duck-typing 是在运行时而不是编译时发生的。我说这就像鸭子类型,因为编译器仍然在编译时进行类型检查,就好像它没有做任何鸭子类型一样。只是在实际使用模板之前不知道类型。
      • 从模板实例化的角度来看,compile-time/runtime-distinction对应pre-instantiation和post-instantiation。恕我直言,编译时/运行时的区别可能最好将其视为“编译时/编译后”区别的一个实例(即“行为在编译时或之前已知/决定”与“之后”) .例如在哪里。 python 在调用 object.hello() 时检查,而不是在编译为字节码时检查,C++ 将在尝试编译 Type1& object::hello(Type1 x, Type2 y) { return x+y;而不是在转动 c = object.hello(a,b);进入这个。
      • 虽然你的立场符合似乎被接受的理解,即鸭式打字意味着运行时检查,但对该术语本身的定义存在一些有效的批评,即使您的答案开头的明确“否”相当有偏见。答案的结尾试图纠正这种偏见。恕我直言,您应该从一开始就以更细致入微的方式回答。
      【解决方案4】:

      不完全是。 Duck 类型(动态类型风格)永远不会产生编译时类型错误,因为它们只是没有任何类型。使用模板,在实例化模板之前您没有类型。一旦你这样做了,变量就会有不同的类型,你确实会遇到编译时错误。

      此外,对于鸭子类型,您可以让一个变量指向不同类型的对象,因为变量只是没有类型。模板无法做到这一点 — 一旦实例化它们,变量就会有一个特定的类型。

      不过,它们是相似的,因为约束是隐式的:只检查实际使用的特征。与多态指针相反,实际类型并不重要。

      【讨论】:

        【解决方案5】:

        是的,有点——例如,如果类型 X 具有带有适当签名的 AddRef()Release()QueryInterface() 方法,则它可以用作带有 CComPtr 模板类的 COM 对象。但这不是完整的鸭子类型 - 仍然对参数强制执行类型检查。

        【讨论】:

          【解决方案6】:

          不,这是一个不同的概念。鸭子类型是一种找出动态类型容器类型的方法。 C++ 模板不是动态类型的,它们使用特定类型进行实例化。

          【讨论】:

            【解决方案7】:

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2012-07-15
              • 2011-03-20
              • 2018-07-25
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2015-01-31
              相关资源
              最近更新 更多