<think>我们正在讨论的是C++模板的使用方法。根据引用内容,模板是C++中用于泛型编程的强大工具,允许编写与类型无关的代码。模板主要分为函数模板和类模板。
引用[1]和[2]提到,模板可以用于函数、类、别名(C++11起)和变量(C++14起)。引用[3]说明了在模板定义中关键字`class`和`typename`的作用相同。引用[4]和[5]分别给出了类模板和函数模板的简单例子。
下面我将详细解释函数模板和类模板的使用方法,并给出示例代码。
1. 函数模板
函数模板允许我们定义一个函数,它可以用于多种数据类型。例如,我们可以写一个通用的交换函数或求最大值的函数。
语法:
```cpp
template <typename T> // 或者 template <class T>
返回类型 函数名(参数列表) {
// 函数体
}
```
示例1:交换两个变量的值
```cpp
template <typename T>
void swap(T &a, T &b) {
T temp = a;
a = b;
b = temp;
}
```
调用时,编译器会根据传入的参数类型自动推导模板参数类型:
```cpp
int a = 1, b = 2;
swap(a, b); // T被推导为int
double x = 1.1, y = 2.2;
swap(x, y); // T被推导为double
```
我们也可以显式指定模板参数:
```cpp
swap<int>(a, b);
```
2. 类模板
类模板允许我们定义一个类,其成员可以使用模板参数作为类型。
语法:
```cpp
template <class T> // 或者 template <typename T>
class 类名 {
// 类成员
};
```
示例2:一个简单的数组类模板
```cpp
template <typename T>
class Array {
private:
T *ptr;
int size;
public:
Array(T arr[], int s);
void print();
};
template <typename T>
Array<T>::Array(T arr[], int s) {
ptr = new T[s];
size = s;
for (int i = 0; i < size; i++)
ptr[i] = arr[i];
}
template <typename T>
void Array<T>::print() {
for (int i = 0; i < size; i++)
cout << *(ptr + i) << " ";
cout << endl;
}
```
使用这个类模板:
```cpp
int arr[5] = {1, 2, 3, 4, 5};
Array<int> a(arr, 5);
a.print();
```
3. 模板参数
模板参数可以有多个,也可以有非类型参数(比如整型常量)。
示例3:带有非类型参数的模板
```cpp
template <typename T, int max>
class Buffer {
T arr[max];
public:
// ...
};
Buffer<int, 100> intBuffer; // 创建一个最大容量为100的整型缓冲区
```
4. 模板特化
有时,对于特定的类型,我们可能需要不同的实现,这时可以使用模板特化。
例如,我们有一个比较函数模板,但对于字符指针类型,我们希望使用字符串比较:
```cpp
// 通用模板
template <typename T>
bool equal(T a, T b) {
return a == b;
}
// 特化:针对const char*类型
template <>
bool equal<const char*>(const char* a, const char* b) {
return strcmp(a, b) == 0;
}
```
5. 注意事项
- 模板的声明和定义通常都放在头文件中,因为编译器需要看到完整的定义才能实例化模板。
- 模板在实例化时才会生成具体的代码,所以如果使用不当,可能会导致代码膨胀。
6. 别名模板(C++11)
C++11引入了别名模板,可以给模板起别名:
```cpp
template <typename T>
using Vec = std::vector<T>;
Vec<int> v; // 等价于 std::vector<int> v;
```
7. 变量模板(C++14)
C++14允许创建变量模板:
```cpp
template <typename T>
constexpr T pi = T(3.1415926);
float f = pi<float>; // 3.1415926f
double d = pi<double>; // 3.1415926
```
总结:
C++模板是泛型编程的基础,它使得代码可以复用,不受具体类型的限制。函数模板和类模板是最常用的两种模板。随着C++标准的更新,模板的功能也在不断增强。
相关问题:
1. 模板实例化有几种方式?
2. 什么是模板的显式实例化和隐式实例化?
3. 模板元编程是什么?有什么应用?
4. 如何避免模板导致的代码膨胀?
5. C++20中概念(concept)是什么?它如何改进模板编程?
</think>### C++ 模板(Template)的使用方法
C++ 模板是一种强大的泛型编程工具,允许编写与数据类型无关的代码。主要分为函数模板和类模板两种形式:
#### 一、函数模板
用于创建通用函数,可处理多种数据类型:
```cpp
// 定义函数模板
template <typename T> // typename 可用 class 替代
T maximum(T a, T b) {
return (a > b) ? a : b;
}
// 使用示例
int main() {
int i = maximum(3, 7); // T 推导为 int
double d = maximum(2.5, 1.8); // T 推导为 double
char c = maximum('z', 'a'); // T 推导为 char
}
```
关键点:
1. `template <typename T>` 声明模板参数
2. `T` 是占位符类型,由编译器推导
3. 支持自动类型推导和显式指定:`maximum<double>(5, 3.2)`
#### 二、类模板
用于创建通用类,成员数据类型可参数化:
```cpp
// 定义类模板
template <typename T>
class Container {
private:
T element;
public:
Container(T arg) : element(arg) {}
T getValue() { return element; }
};
// 使用示例
int main() {
Container<int> intContainer(100); // T=int
Container<string> strContainer("Hello");// T=string
cout << intContainer.getValue(); // 输出 100
}
```
关键点:
1. 类外定义成员函数需重复模板声明:
```cpp
template <typename T>
T Container<T>::getValue() { /*...*/ }
```
2. 模板参数可指定默认值:
```cpp
template <typename T = int>
```
#### 三、高级用法
1. **多参数模板**:
```cpp
template <typename T, typename U>
class Pair {
T first;
U second;
};
Pair<int, double> point(1, 3.14);
```
2. **非类型模板参数**:
```cpp
template <typename T, int size>
class Array {
T arr[size];
};
Array<double, 10> doubleArray;
```
3. **模板特化**(特定类型的定制实现):
```cpp
template <> // 全特化
class Container<char*> {
// 针对char*类型的特殊实现
};
```
#### 四、使用注意事项
1. 模板定义通常需放在头文件中(编译器需在编译时实例化)
2. `typename` 和 `class` 可互换,但 `typename` 更清晰地表示类型[^3]
3. 模板在实例化时才生成具体代码,可能增加编译时间
4. C++17 引入类模板参数推导:
```cpp
Container intContainer(100); // 自动推导T=int
```
#### 五、应用场景
1. 通用容器(`vector`, `map` 等 STL 组件)
2. 数学库(矩阵、向量等数值计算)
3. 算法实现(排序、查找等通用算法)
4. 工厂模式和策略模式实现
> 模板是泛型编程的核心,通过抽象数据类型实现代码复用。STL(标准模板库)90%的组件都基于模板实现[^1]。
***