2011-08-03 14 views

回答

13

对我来说,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++中获得的鸭子打字差不多。

+7

从我对鸭子打字的有限理解,你对复制功能的描述听起来就像使用鸭子打字一样。鸭子打字的特征究竟是什么,C++模板没有“完成”? – aioobe

+5

@aioobe:据我所知,鸭编程是在运行时发生的,而不是编译时。我说这就像鸭子打字,因为编译器在编译时仍然会进行类型检查,就好像它没有进行任何鸭子输入一样。只是在实际使用模板之前,这些类型才是已知的。 –

+0

从模板实例化的角度来看,编译时/运行时区分对应于预实例化和后实例化。恕我直言,编译时/运行时区别可能更好地被认为是“编译时/后编译时”区分的一个实例(即“行为在编译时或之前已知/决定”与“事后”)。 。例如, python会在调用object.hello()时进行检查,而不是在编译为字节码时,C++会在尝试编译Type1&object :: hello(Type1 x,Type2 y)时检查它(返回x + y; }而不是在转向时c = object.hello(a,b);进入这个。 –

3

是,排序的 - 例如,如果类型X具有AddRef()Release()QueryInterface()方法用适当的签名可以用作与CComPtr模板类一个COM对象。但是这不是完整的鸭子打字 - 类型检查仍然针对参数执行。

2

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

4

不完全。 Duck类型(动态类型样式)决不会产生编译时类型错误,因为它们没有任何类型。使用模板,除非实例化模板,否则不需要类型。一旦你这样做了,变量就会有明显的类型,你确实会得到编译时错误。

另外,对于鸭子类型,你可以有一个变量指向不同类型的对象,因为变量没有类型。这对模板来说是不可能的 - 一旦你实例化了它们,变量就有一个特定的类型。

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

59

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

如果某些内容不正确(例如复制构造函数丢失),则编译失败。 与非鸭子类型的 调用函数时,实际ducktyping中的对应部分是失败的。在这里它会在运行时发生。

+0

嗯..我从鸭打字的理解是,你试图找出类型。这意味着你遇到了一个动态的对象,你不知道类型。在C++模板中,你必须确定类型,以便实例化它。 – duedl0r

+4

-1。鸭子打字不一定意味着动态打字或运行时检查。编译时鸭子打字仍然是鸭子打字。 –

+0

C++模板最初基于令牌重放。这仍然表现出它的鸭子般的属性。 –

10

鸭打字意味着,“如果它叫起来像鸭子,走起来像鸭子,那么它就是鸭子”。它没有计算机科学的正式定义,因此我们无法比较C++。

C++是不相同的(例如)的Python,当然,但它们都具有的隐式定义的接口的概念。作为Python函数参数使用的对象所需的接口是函数执行的任何操作。用作C++模板参数的类型所需的接口是模板用于该类型的对象的任何操作。这就是相似性,这就是评估C++模板的理由。

而且,因为模板参数推导的,在C++中,你可以尝试通过任何旧的对象,编译器会弄清楚它是否能够实例化函数模板。

一个区别是,在C++中,如果参数不呱,那么编译器的对象。在Python中,只有运行时对象(只有在函数实际被调用时,如果代码中有条件)。这是一个对象/类型所要求的接口性质的区别 - 在C++中,模板要求特定的表达式是有效的,或者它不需要。在Python中,必要的有效表达式可以依赖于早期必要表达式的运行时值。所以在Python中,你可以要求一个对象要么大声地安静,要么大声地嘎嘎,它也需要走路。在C++中,你可以做到这一点的条件dynamic_cast,如果量是一个编译时间常数,你可以做到这一点模板特例,但你不能用静态类型说,鸭子只需要走路,如果quack_volume()回报loud。当然,在Python中,所需的接口可能并不是真正的“必需的” - 如果方法不存在,则行为是抛出异常,并且如果发生这种情况,可能会记录并保证调用者的行为。

给你,使这种差异意味着C++没有它,你是否定义“鸭打字”。