函数模板是指函数逻辑结构相同,但是参数类型不同的一类函数的抽象,即类型参数化。引用官方描述如下:
模板把函数或类要处理的数据类型参数化,表现为参数的多态性,称为类属。
模板用于表达逻辑结构相同,但具体数据元素类型不同的数据对象的通用行为。
下面写一个函数模板的实例,通过实例分析函数模板的语法和使用规则
1. #include <iostream> 2. using namespace std; 3. 4. template<typename T> 5. void my_print(T a, T b) 6. { 7. cout << "模板函数 " << a << " " << b << endl; 8. } 9. 10. void my_print(int a, int b) 11. { 12. cout << "普通函数 (int a, int b) " << a << " " << b << endl; 13. } 14. 15. void my_print(int a, char b) 16. { 17. cout << "普通函数 (int a, char b) " << a << " " << b << endl; 18. } 19. 20. int main() 21. { 22. my_print(1, 2); //优先匹配普通函数 23. 24. my_print('a', 4); //调用 my_print(int a, int b) 并会自动进行类型转换,把 'a' 转换为 int 型 25. 26. my_print('a', 'b'); //调用模板函数,模板函数严格进行参数类型匹配,并会自动推导参数类型 27. //只有调用时两个参数类型完全一致且没有普通函数匹配的时候才会调用模板函数(参数更佳匹配) 28. 29. my_print<char>('a', 'b'); //显式参数类型 30. 31. my_print<>(1, 2); //强制使用模板函数,不会在调用 my_print(int a, int b) 32. 33. //my_print<>(1, 'a'); //错误 C2672 “my_print” : 未找到匹配的重载函数 34. //函数模板不会进行参数类型转换 35. 36. 37. system("pause"); 38. return 0; 39. }
编译并执行上面的程序可以看到打印的结果和我们在程序中分析的规则一致
另外,如果把上面注释掉的语句放开
my_print<>(1, 'a');
也就是强制使用模板函数,并传入两个类型不同的参数,再次编译可以看到编译器报错
这证明了我们所分析的,模板函数不会进行参数自动类型转换。
最后函数模板的实现并不是提前把所有可能的参数类型都列举出来并生成相应的函数,而是二次编译理论。函数模板的实现机制实际是两次编译,第一次编译是在模板函数声明的地方进行编译;第二次编译是在模板函数调用的地方,对参数替换后的函数进行编译。