导入
函数模板和类模板
学习如何定义和使用函数模板与类模板,以创建灵活且高性能的代码,使其能够无缝地与任何数据类型配合使用。
1int get_max(int a, int b) { 2 if (a>=b) 3 return a; 4 return b; 5} 6 7double get_max(double a, double b) { 8 if (a>=b) 9 return a; 10 return b; 11}
1#include <iostream> 2#include <string> 3 4// 定义一个函数模板 5// 'T' 是数据类型的占位符 6template <typename T> 7T get_max(T a, T b) { 8 if (a>=b) 9 return a; 10 else 11 return b; 12} 13 14int main() { 15 int i1 = 10, i2 = 20; 16 double d1 = 5.5, d2 = 2.1; 17 std::string s1 = "Apple", s2 = "Orange"; 18 19 // 编译器推导出 T = int 20 std::cout << "Max int: " << get_max(i1, i2) << "\n"; 21 22 // 编译器推导出 T = double 23 std::cout << "Max double: " << get_max(d1, d2) << "\n"; 24 25 // 编译器推导出 T = std::string 26 std::cout << "Max string: " << get_max(s1, s2) << "\n"; 27 28 return 0; 29}
1#include <iostream> 2#include <string> 3 4// 一个简单的泛型容器类 5template <typename T> 6class Box { 7private: 8 T value; // 变量 'value' 将具有类型 T 9 10public: 11 // 构造函数接受类型为 T 的值 12 Box(T v) : value(v) {} 13 14 // 获取器返回类型 T 15 T get_value() const { 16 return value; 17 } 18 19 // 设置器接受类型 T 20 void set_value(T v) { 21 value = v; 22 } 23}; 24 25int main() { 26 // 实例化一个整数的 Box 27 Box<int> intBox(123); 28 std::cout << "Int Box: " << intBox.get_value() << "\n"; 29 30 // 实例化一个字符串的 Box 31 Box<std::string> strBox("Hello Templates"); 32 std::cout << "String Box: " << strBox.get_value() << "\n"; 33 34 // C++17/20:类模板参数推导(CTAD) 35 // 编译器从参数 3.14 推导出 <double> 36 Box doubleBox(3.14); 37 std::cout << "Double Box: " << doubleBox.get_value() << "\n"; 38 39 return 0; 40}
你还记得吗?
我们实际上从本课程开始就一直在使用类模板。当我们编写
std::vector<int>或std::map<std::string, int>时,我们正在实例化标准库中定义的模板。标准库开发者只需编写一次 vector 的逻辑。当我们使用它时,编译器会生成管理整数、字符串或自定义对象动态数组所需的特定代码。这解释了为什么 C++ 容器如此高效:
std::vector<int>并不是一个在运行时进行类型检查的通用“对象集合”;它是一个针对整数高度优化的数组。