什么是模板
模板是一种通用的编程工具,允许程序员编写通用的类或函数,以便在不同的数据类型上进行操作。模板可以让程序员编写一次代码,然后根据需要在编译时生成特定类型的代码实例。这种特性统称为泛型编程。
void Swap(int& a, int& b) { int temp = a; a = b; b = temp; } void Swap(double& a, double& b) { int temp = a; a = b; b = temp; }
在上面例子中可以看出,当我想要进行两个对象之间的交换时,由于每次交换对象的类型不同,所以要重复写多个
Swap
函数,为了解决这个问题,模板就出现了。template <typename T> void Swap(T& a, T& b) { T temp = a; a = b; b = temp; }
使用模板的优势:
- 代码重用:可以编写通用的代码,减少重复编写类似功能的代码。
- 类型安全:编译器可以在编译时进行类型检查,确保类型安全性。
- 灵活性:可以在不同的数据类型上使用想同的模板,提高代码的灵活性和可扩展性。
函数模板
定义
函数模板:允许编写通用的函数,可以用于处理不同类型的数据。函数模板使用template <typename T>
或template <class T>
来定义,T
是模板参数,表示可以是任意类型。函数模板的实例化
函数模板的实例化是指在使用函数模板时,编译器根据具体的数据类型生成实际的函数代码。
隐式实例化:是指在程序中使用函数模板时,编译器自动根据传递的参数类型推断出模板参数的类型,并生成对应的函数。
template <typename T> T add(const T& a, const T& b) { return a + b; } int main() { int x1 = add(1, 2);// 隐式实例化为 int add(const int& a, const int& b) double x2 = add(3.1, 4.2);// 隐式实例化为 double add(const double& a, const double& b) return 0; }
显示实例化:在函数名后的<>中指定模板参数的实际类型
int main() { int x1 = add<int>(1, 2); double x2 = add<double>(3.1, 4.2); }
模板参数的匹配原则
精确匹配优先原则:如果存在完全匹配的模板实例化,编译器会优先选择完全匹配的模板函数。
#include <iostream> using namespace std; template <typename T> void foo(T a) { cout << "foo(T a) is called" << endl; } template <> void foo<int>(int a) { cout << "foo<int>(int a) is called" << endl; } int main() { foo(5); // 输出 "foo<int>(int a) is called" foo(3.14); // 输出 "foo(T a) is called" return 0; }
在上述代码中,定义了一个函数模板
foo
,同时还定义了一个特化版本foo<int>
。当调用foo(s)
时,由于存在精确匹配的特化版本,会选择特化版本而不是通用版本。模板参数推断:编译器会根据传递的参数类型推断模板参数的类型。在函数模板调用时,如果模板参数类型可以从函数参数类型推断出来,则编译器会自动推断模板参数的类型
#include <iostream> using namespace std; template <typename T> void foo(T a) { cout << "foo(T a) is called" << endl; } int main() { foo(5); // 输出 "foo(T a) is called" foo(3.14); // 输出 "foo(T a) is called" return 0; }
当调用
ffo(5)
时,由于5
是一个int
类型,函数模板会选择匹配int
类型的实例化版本;当调用foo(3.14)
时,由于3.14
是一个double类型,函数模板会选择匹配double
类型的实例化版本。注意:这种方式无法编译通过
template<class T> T Add(const T& left, const T& right) { return left + right; } int main() { Add(1, 1.1); return 0; }
由于参数列表中中有一个
T
,编译器无法确定此处到底该将T
确定为int
或者double
类型而报错。
类模板
标签:Container,函数,int,实例,类型,模板 From: https://www.cnblogs.com/zhiheng-/p/18156120示例
template <class T> class Container { public: Container(int size) { data = new T[size]; _size = size; } ~Container();//类中声明,类外定义 T& operator[](int index) { return data[index]; } int getSize() const { return size; } private: T* data; int _size; }; //注意:类模板中函数放在类外进行定义时,需要加模板参数列表 template <class T> Container<T>::~Container() { delete[] date; }
在上述代码中,我们定义了一个类模板
Container
,其中存储的元素类型由模板参数T
指定。当我们使用Container<int>
实例化类模板时,会生成一个存储int
类型元素的容器类;当我们使用Container<double>
实例化类模板时,会生成一个存储double
类型元素的容器类。类模板的实例化
类模板实例化需要在类模板名字后跟<>,然后将实例化的类型放在<>中即可,类模板不是真正的类,而实例化的结果才是。//Container是类名,Container<int>才是类型 Container<int> s1; Container<double> s2;