【发布时间】:2011-10-18 21:27:13
【问题描述】:
对我来说,C++ 模板使用了鸭子类型的思想,对吗?是不是表示模板类或方法中引用的所有泛型类型都是鸭子类型?
【问题讨论】:
标签: c++ templates duck-typing
对我来说,C++ 模板使用了鸭子类型的思想,对吗?是不是表示模板类或方法中引用的所有泛型类型都是鸭子类型?
【问题讨论】:
标签: c++ templates duck-typing
对我来说,C++ 模板是鸭子类型的编译时版本。 编译器将编译例如上课,只要你的鸭子 具有所有需要的类型,它将实例化一个类。
如果某些地方不正确(例如缺少复制构造函数),则编译失败。 当您使用 非鸭型。在这里它会在运行时发生。
【讨论】:
鸭子打字的意思是,“如果它像鸭子一样嘎嘎叫,像鸭子一样走路,那么它就是一只鸭子”。它在计算机科学中没有正式的定义供我们比较 C++。
当然,C++ 与(例如)Python 不同,但它们都有隐式定义接口的概念。用作 Python 函数参数的对象所需的接口是函数对其执行的任何操作。用作 C++ 模板参数的类型所需的接口是模板对该类型的对象所做的任何事情。这就是相似性,也是评估 C++ 模板的依据。
此外,由于模板参数推导,在 C++ 中你可以尝试传递任何旧对象,编译器会判断它是否可以实例化函数模板。
一个不同之处在于,在 C++ 中,如果参数不嘎嘎作响,则编译器对象。在 Python 中,只有运行时对象(并且仅当函数被实际调用时,如果代码中有条件)。这是对象/类型所要求的接口性质的差异——在 C++ 中,模板要求特定表达式有效,或者不需要。在 Python 中,必要的有效表达式可以依赖于早期必要表达式的运行时值。因此,在 Python 中,您可以请求一个可以大声或安静地嘎嘎叫的物体,如果它大声嘎嘎叫,它也需要走路。在 C++ 中,你可以通过条件 dynamic_cast 来做到这一点,如果卷是编译时常量,你可以使用模板特化,但你不能使用静态类型来说鸭子只需要在 @987654322 时行走@ 返回loud。当然,在 Python 中,所需的接口可能并不是真正“必需的”——如果方法不存在,则行为是抛出异常,如果发生这种情况,可能会记录并保证调用者的行为。
取决于你是否定义“鸭子类型”,以便这种差异意味着 C++ 没有它。
【讨论】:
对我来说,C++ 模板使用了鸭子类型的思想,对吗?
不,C++ 模板用于实现通用代码。也就是说,如果您的代码可以使用多种类型,则不必为每种类型复制它。 std::vector 和 std::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++ 中的鸭子类型一样接近。
【讨论】:
不完全是。 Duck 类型(动态类型风格)永远不会产生编译时类型错误,因为它们只是没有任何类型。使用模板,在实例化模板之前您没有类型。一旦你这样做了,变量就会有不同的类型,你确实会遇到编译时错误。
此外,对于鸭子类型,您可以让一个变量指向不同类型的对象,因为变量只是没有类型。模板无法做到这一点 — 一旦实例化它们,变量就会有一个特定的类型。
不过,它们是相似的,因为约束是隐式的:只检查实际使用的特征。与多态指针相反,实际类型并不重要。
【讨论】:
是的,有点——例如,如果类型 X 具有带有适当签名的 AddRef()、Release() 和 QueryInterface() 方法,则它可以用作带有 CComPtr 模板类的 COM 对象。但这不是完整的鸭子类型 - 仍然对参数强制执行类型检查。
【讨论】:
不,这是一个不同的概念。鸭子类型是一种找出动态类型容器类型的方法。 C++ 模板不是动态类型的,它们使用特定类型进行实例化。
【讨论】:
【讨论】: