为什么我们需要为每个类函数定义指定类型模板参数?

时间:2015-12-13 22:04:26

标签: c++ templates header

由于我们在类声明中定义了模板类型,为什么我们必须在每个函数定义后指定它?我很困惑,因为它甚至在同一个文件中,因此似乎几乎没有必要在每个函数上指定它,因为我们使用::运算符,它不应该返回类声明并看到{{1已定义。

我是c ++的新手,仍然需要澄清一些误解。

T

2 个答案:

答案 0 :(得分:0)

首先,您可以将参数重命名为正常函数:

template <class U> bool FooBar<U>::foo1(U and_here_too){/**/}

它还设法处理(部分)专业化:

template <> bool FooBar<int>::foo1(int i){/**/}
template <typename T> bool FooBar<std::vector<T>>::foo1(std::vector<T> v){/**/}

答案 1 :(得分:0)

模板是通用编程的示例。我们的想法是重用代码/算法。在具有严格类型控制的语言中,您会遇到看似不必要的约束。例如,您可能有一些排序功能在一个项目中表现出色,但与另一个项目中使用的类型不兼容。

C ++,C#和Java将泛型编程作为模板(C ++)和泛型(C#,Java)引入。在泛型中(让我们来谈谈Java)类是现有实体,类参数主要用作类型控制服务。这是他们收藏的目的。当您检查列表的工作方式时,您会看到列表收集对象并仅在检索到对象时转换回参数化类型。在编写类时,您只能假设参数化类型是Object或声明的接口,如下例所示:

class Test<T extends Comparable> {}

在这里你可以使用T作为Comparable。除非您明确声明接口,否则该参数将被视为Object。

现在出现了泛型和模板之间的区别。在C ++中,您可以更多地了解实现中的参数化类型。您可以编写未知类型的对象的排序。在Java中,您必须至少知道参数类型的接口是什么。这导致C ++必须为每个参数构建新类(以便检查代码是否正确)。 Vector<int> **与** Vector<float>完全分开。在Java中,存在一个类Vector<? extends Comparable>

::是范围运算符。您可以访问Vector<int>的范围,因为该类存在,但Vector没有。

因此,Java可以编译泛型,而C ++则不能。所有模板必须以标题提供给所有程序员;你无法隐藏它(有一些工作来编译模板,但我不知道它的状态是什么)。

因此,当您使用泛型时,您可以引用方法Vector.add(),而当模板必须指定参数template<class T> Vector<T>时。

PS。由于模板参数是类名的组成部分,因此您可以使用模板进行编译时计算,如fibonaci序列

template<int N> struct Fibonaci {
  static const int element = Fibonacci<N-1>::data + Fibonacci<N-2::data>;
}
template<1> struct Fibonaci {
  static const int element = 1;
}
template<0> struct Fibonaci {
  static const int element = 0;
}
相关问题