当编译器遇到一个模板定义时,它并不生成代码。只有当我们实例化出模板的一个特定版本时,编译器才会生成代码。当我们使用(而不是定义)模板时,比编译器才生成代码。这一特性影响了我们如何组织代码以及错误何时被检测到。
通常,当我们调用一个函数时,编译器只需要掌握函数的声明。类似的,当我们使用一个类类型的对象时,类定义必须是可用的,但成员函数的定义不必已经出现。因此我们将类定义和函数声明放在头文件中,而普通函数和类的成员函数的定义放在源文件中。
模板则不同:
为了生成一个实例化版本,编译器需要掌握函数模板或类模板成员函数的定义。
因此,与非模板代码不同,模板的头文件通常即包括声明也包括定义。总结一下:
模板的具体实现被称为实例化或具体化。
因为模板不是函数,他们不能单独编译,模板必须与特定的模板实例化请求一起使用。
因此,最简单的方法是将所有模板信息放在一个头文件中,并在要使用这些模板的文件中包含该头文件。
头文件
源文件
需要注意的是源文件中需要进行显示实例化,这与一般函数不同,否则报错。
另外每种需要使用到的类型都需要单独显示实例化,比如,假如后面还需要用到Point2d的计算,则需要在源文件后另外添加一个实例化
template double getAngle3d(Point2d, Point2d);