🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
## [$]一.模板编译 1. 模板定义时,编译器并不生成代码,只有实例化模板的特定版本时,编译器才生成代码。 2. 对于类模板,只有使用过的成员函数才会生成代码。 3. 为了生成一个实例化版本, **编译器需要掌握函数模板或类模板成员函数的定义** 。因此,与非模板代码不同,模板的头文件通常既包括声明也包括定义。 > 假如我们将栈类 Stack 的类声明放在头文件 `stack.h` ,成员函数的定义放在 cpp 文件 `stack.cpp` ,然后在需要使用它的地方 `main.cpp` 只引入头文件,那么连接的时候会报 **函数不存在** 的错误。 > 问题分析: > 1. 编译器会将头文件的代码拷贝到 `main.cpp` ,这时,在类模板实例化(用这个类去创建对象)的时候,编译器不能在 `main.cpp` 内找到相关成员函数的定义,就不会生成相应的代码到 `main.obj` 。 > 2. 编译 `stack.cpp` 时,因为没有类模板实例化,所以编译器不生成这些成员函数的代码到 `stack.obj`。 > 3. 连接的时候,所有 `.obj` 文件都没有相应成员函数的代码,会报 **函数不存在** 的错误。 > > 解决方法: > 1. 将成员函数定义的代码放入头文件。 > 2. 使用它的时候引入 `stack.cpp` 文件,而不是引入 `stack.h` 。 ## [$]二.模板编译与错误检查 通常,编译器会在三个阶段报告错误: 1. 编译模板本身时。在这个阶段,编译器通常不会发现很多错误。编译器可能检查语法错误,例如忘记分号或者变量名拼错等,但也就这么多了。 2. 编译器遇到模板使用时。在此阶段,编译器仍然没有很多可检查的。对函数模板调用,编译器通常会检查实参数目是否正确。它还能检查参数类型是否匹配。对于类模板,编译器可以检查用户是否提供了正确数目的模板实参,但也仅限于此了。 3. 模板实例化时。只有这个阶段才能发现类型相关的错误。依赖于编译器如何管理实例化,这类错误可能在链接时才报告。 > 简单来说,只要不使用那些模板类,不使用相应的成员函数,那么编译器基本上不会检测里面的语法错误。 >[success] 在测试模板类时,最好用它创建一个对象,并调用其所有的成员函数。