C++模板是C++语言的一种特性,它允许程序员创建与类型无关的函数和类。通过使用模板,您可以编写一份代码,然后让编译器根据具体的数据类型来生成多个版本的函数或类。这极大地提高了代码的重用性和灵活性。
函数模板
函数模板用于定义可以接受任意数据类型的函数。在函数模板中,类型被用作参数,就像常规函数参数一样。
cpp复制代码
|
template <typename T> // 声明一个类型参数T |
|
T add(T a, T b) { // 使用类型参数T定义函数 |
|
return a + b; |
|
} |
|
|
|
int main() { |
|
int x = 5, y = 10; |
|
double a = 1.5, b = 2.5; |
|
std::cout << "x + y = " << add(x, y) << std::endl; // 调用add<int> |
|
std::cout << "a + b = " << add(a, b) << std::endl; // 调用add<double> |
|
return 0; |
|
} |
在上面的例子中,add 是一个函数模板,它可以接受任何类型 T 的两个参数,并返回它们的和。当我们在 main 函数中调用 add 时,编译器会为每种不同的类型(int 和 double)生成一个特定的函数版本。
类模板
类模板用于定义可以接受任意数据类型的类。与函数模板类似,类型参数在类模板的声明中使用。
cpp复制代码
|
template <typename T> // 声明一个类型参数T |
|
class Array { |
|
private: |
|
T* arr; |
|
size_t size; |
|
public: |
|
Array(T arr[], size_t s); |
|
void print(); |
|
// ... 其他成员函数 ... |
|
}; |
|
|
|
template <typename T> |
|
Array<T>::Array(T arr[], size_t s) { |
|
size = s; |
|
this->arr = new T[s]; |
|
for (size_t i = 0; i < s; i++) { |
|
this->arr[i] = arr[i]; |
|
} |
|
} |
|
|
|
template <typename T> |
|
void Array<T>::print() { |
|
for (size_t i = 0; i < size; i++) { |
|
std::cout << arr[i] << " "; |
|
} |
|
std::cout << std::endl; |
|
} |
|
|
|
int main() { |
|
int intArr[] = {1, 2, 3, 4, 5}; |
|
Array<int> a(intArr, 5); |
|
a.print(); // 输出: 1 2 3 4 5 |
|
|
|
double doubleArr[] = {1.1, 2.2, 3.3, 4.4}; |
|
Array<double> b(doubleArr, 4); |
|
b.print(); // 输出: 1.1 2.2 3.3 4.4 |
|
|
|
return 0; |
|
} |
在这个例子中,Array 是一个类模板,它可以存储任何类型 T 的数组。我们在 main 函数中创建了两个 Array 对象:一个用于 int 类型,另一个用于 double 类型。编译器会为每种类型生成一个特定的类版本。
类型推导
从C++11开始,编译器能够自动推导模板参数的类型,这称为类型推导。因此,在调用函数模板或创建类模板的实例时,通常可以省略模板参数。
cpp复制代码
|
// 函数模板类型推导示例 |
|
int main() { |
|
int sum = add(3, 4); // 类型推导为 add<int> |
|
double prod = add(3.0, 4.0); // 类型推导为 add<double> |
|
return 0; |
|
} |
|
|
|
// 类模板类型推导示例 |
|
int main() { |
|
Array<int> a = {1, 2, 3, 4, 5}; // 显式指定类型 |
|
Array b = {1.1, 2.2, 3.3, 4.4}; // 类型推导为 Array<double> |
|
return 0; |
|
} |
模板是C++中非常强大的工具,它们允许程序员创建通用和可重用的代码,而无需为每个数据类型编写特定的版本。然而,模板的使用也可能导致编译时间的增加,因为对于每种新的类型组合,编译器都需要生成新的代码。因此,在使用模板时需要权衡代码重用和编译时间。