函数模板和类模板是泛型编程的重要工具。它们允许你编写与类型无关的代码,从而可以处理多种类型。
函数模板
用于生成多种类型的函数。
template <typename T>
T add(T a, T b) {
return a + b;
}
在这个例子中,add
是一个函数模板,它接受两个同类型的参数并返回它们的和。你可以用不同的类型来实例化这个模板:
#include <iostream>
template <typename T>
T add(T a, T b) {
return a + b;
}
int main() {
std::cout << add(3, 5) << std::endl; // 输出 8 (int)
std::cout << add(3.5, 2.5) << std::endl; // 输出 6.0 (double)
std::cout << add<std::string>("Hello, ", "World!") << std::endl; // 输出 "Hello, World!" (string)
return 0;
}
不通过参数实例化:
直接调用 函数名<类型参数列表>(列表参数)
#include <iostream>
using namespace std;
template <class T>
T Inc(T n)
{
return 1 + n;
}
int main()
{
cout << Inc<double>(4) / 2; //输出 2.5
return 0;
}
函数模板的重载
函数模板可以重载,只要它们的形参表或类型参数表不同即可。
template <class T1, class T2>
void print(T1 arg1, T2 arg2)
{
cout << arg1 << " " << arg2 << endl;
}
template <class T>
void print(T arg1, T arg2)
{
cout << arg1 << " " << arg2 << endl;
}
template <class T, class T2>
void print(T arg1, T arg2)
{
cout << arg1 << " " << arg2 << endl;
}
函数模板和函数的次序
再有多个函数和函数模板名字相同的情况下,编译器如下处理一条函数调用语句:(匹配模板函数时,不进行类型自动转换)
1.先找参数完全匹配的普通函数(非由模板实例化而得的函数)。
2.再找参数完全匹配的模板函数。
3.再找实参数经过自动类型转换后能够匹配的普通函数。
类模板
用于定义与类型无关的类。
template <typename T>
class Container {
public:
Container() : element(T()) {}
void set(const T& elem) { element = elem; }
T get() const { return element; }
private:
T element;
};
在这个例子中,Container
是一个类模板,可以存储任何类型的元素。你可以用不同的类型来实例化这个类模板:
#include <iostream>
#include <string>
template <typename T>
class Container {
public:
Container() : element(T()) {}
void set(const T& elem) { element = elem; }
T get() const { return element; }
private:
T element;
};
int main() {
Container<int> intContainer;
intContainer.set(42);
std::cout << intContainer.get() << std::endl; // 输出 42
Container<std::string> strContainer;
strContainer.set("Hello, Templates!");
std::cout << strContainer.get() << std::endl; // 输出 "Hello, Templates!"
return 0;
}
注意事项
模板参数:你可以使用 typename
或 class
来声明模板参数,它们在这个上下文中是等效的。
模板特化:可以提供特定类型的实现,这称为模板特化。例如,你可以对某个特定的类型进行特化:
template <>
std::string add<std::string>(std::string a, std::string b) {
return a + " " + b; // 对字符串特别处理
}
非类型模板参数:除了类型类型泛型参数外,你还可以使用非类型参数。
template <typename T, int size>
class Array {
public:
T& operator[](int index) { return data[index]; }
private:
T data[size];
};
模板实例化:当编译器遇到使用模板的语句时,它根据提供的参数创建实际的函数或类定义。编译
时间较长:因模板实例化在编译时生成代码,过度使用模板可能导致编译时间增加。