C ++模板和鸭子打字有什么关系?

对我来说,C ++模板使用了鸭子打字的想法,对吗? 是否意味着模板类或方法中引用的所有generics都是鸭子types?

对我来说,C ++模板使用了鸭子打字的想法,对吗?

不,C ++模板被用来实现generics代码。 也就是说,如果您的代码可以使用多种types,则不必为每种types重复使用。 诸如std::vectorstd::list就是这个实例的明显例子。 C ++模板被滥用于做其他事情,但通用性是最初的意图。

是否意味着模板类或方法中引用的所有generics都是鸭子types?

不,像C ++中的其他types一样,它们只是“正常”types。 它们只是在模板实际实例化之前才知道。

但是,可以使用模板来实现类似于鸭子的input。 迭代器就是一个例子。 考虑这个function:

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

请注意, copy函数可以接受任何types的参数因为它实现了不等式运算符,解引用运算符和后缀增量运算符。 这可能与您在C ++中获得的鸭子打字差不多。

对我来说,C ++模板是一个鸭编程的编译时版本。 编译器会编译例如Class,只要你的Duck具有所有需要的types,它就会实例化一个类。

如果某些内容不正确(例如复制构造函数丢失),则编译失败。 当你用一个非鸭式函数调用一个函数时,实际鸭式的对应是失败的。 在这里它会在运行时发生。

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

当然,C ++与Python不完全相同,但它们都有一个隐式定义接口的概念。 作为Python函数参数使用的对象所需的接口是函数执行的任何操作。 用作C ++模板参数的types所需的接口是模板用于该types的对象的任何操作。 这就是相似之处,这就是评估C ++模板的理由。

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

一个区别是,在C ++中,如果参数不嘎嘎声,那么编译器对象。 在Python中,只有运行时对象(只有在函数被实际调用时,如果代码中有条件)。 这是一个对象/types所要求的接口的性质的区别 – 在C ++中,模板要求特定的expression式是有效的,或者它不需要。 在Python中,必要的有效expression式可以依赖于早期必要expression式的运行时值。 所以在Python中,你可以要求一个对象,要么大声地或平静地嘎嘎,如果它大声地嘎嘎声,它也需要走路。 在C ++中,你可以通过条件dynamic_cast ,如果这个卷是一个编译时常量,你可以使用模板特化,但是你不能使用静态types来说鸭子只有在quack_volume() loud 。 当然,在Python中,所需的接口可能不是真正的“必需的” – 如果方法不存在,则行为是抛出一个exception,如果发生这种情况,可能会logging和保证调用者的行为。

由您决定是否定义“鸭子打字”,以便这种差异意味着C ++没有它。

不完全是。 Ducktypes(dynamictypes样式)永远不会产生编译时types错误,因为它们没有任何types。 使用模板,在实例化模板之前,您没有types。 一旦你做了,variables有不同的types,你确实会得到编译时错误。

另外,对于鸭子types,你可以有一个variables指向不同types的对象,因为variables没有types。 这是不可能的模板 – 一旦你实例化它们,variables有一个特定的types。

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

是的,例如,如果typesX具有带有适当签名的AddRef()Release()QueryInterface()方法,则可以将其用作具有CComPtr模板类的COM对象。 但是这不是完整的鸭子打字 – types检查仍然是强制参数。

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

维基百科涵盖了这个区别 。