外观
函数模板和类模板有什么区别?
⭐ 题目日期:
金山 - 2024/12/31
📝 题解:
函数模板和类模板是 C++ 中泛型编程的核心工具,它们的核心区别在于应用场景、实例化方式和类型推导机制。以下是详细对比:
1. 核心定义
函数模板 | 类模板 |
---|---|
定义通用函数,接受任意类型参数 | 定义通用类,成员数据或函数依赖模板参数 |
```cpp | ```cpp |
template <typename T> | template <typename T> |
T max(T a, T b) { | class Stack { |
return (a > b) ? a : b; | T* elements; |
} | // ... |
``` | }; |
``` |
2. 实例化方式
函数模板 | 类模板 |
---|---|
隐式实例化(编译器自动推导类型) | 显式实例化(必须指定类型) |
```cpp | ```cpp |
max(3, 5); // T → int | Stack< int> intStack; |
max(2.5, 3.8); // T → double | Stack<string>strStack; |
``` | ``` |
若无法推导,需显式指定: | C++17 后支持类模板参数推导(CTAD) |
```cpp | ```cpp |
max<double> (2, 3.5); | vector vec{1, 2, 3}; // vector<int> |
``` | ``` |
3. 类型推导能力
函数模板 | 类模板 |
---|---|
支持参数类型推导 | 传统上不支持类型推导 |
例如:auto result = max(3, 5); | C++17 前必须显式指定类型 |
编译器根据实参推断 T | C++17 后可通过推导指引简化 |
```cpp | ```cpp |
template <typename T> | template <typename T> |
void print(T value) | class MyPair { |
print("Hello"); // T → const char* | T first, second; |
``` | }; |
MyPair p(1, 2); // C++17: T → int | |
``` |
4. 使用场景
函数模板 | 类模板 |
---|---|
适用于通用算法(如排序、比较) | 适用于通用数据结构(如容器、包装类) |
```cpp | ```cpp |
template <typename T> | template <typename T> |
void sort(T arr[], int size); | class Array { |
``` | T* data; |
// ... | |
}; | |
``` |
5. 特化与重载
函数模板 | 类模板 |
---|---|
支持重载和特化 | 仅支持特化(不支持重载) |
```cpp | ```cpp |
// 重载 | // 全特化 |
template <typename T> | template <> |
void print(T value); | class Stack<int> { ... }; |
// 特化 | // 偏特化 |
template <> | template <typename T> |
void print<int> (int value); | class Stack<T*> { ... }; |
``` | ``` |
6. 成员函数模板
函数模板 | 类模板 |
---|---|
无此概念 | 类模板中可定义成员函数模板 |
```cpp | ```cpp |
template <typename T> | template <typename U> |
class MyClass { | void copyFrom(const MyClass<U> & other); |
public: | ``` |
template <typename U> | |
void process(U value); | |
}; | |
``` |
7. 默认模板参数
函数模板 | 类模板 |
---|---|
C++11 前不支持默认模板参数 | 支持默认模板参数 |
C++11 后支持: | ```cpp |
```cpp | template <typename T = int> |
template <typename T = int> | class Box { ... }; |
void log(T value = T{}); | Box<> defaultBox; // T → int |
``` | ``` |
总结
特性 | 函数模板 | 类模板 |
---|---|---|
核心目标 | 定义类型无关的函数 | 定义类型无关的类 |
类型推导 | 支持(隐式实例化) | C++17 前不支持,之后支持推导指引 |
实例化方式 | 隐式或显式 | 显式(C++17 后部分隐式) |
典型应用 | 算法(如 sort , swap ) | 容器(如 vector , map ) |
重载与特化 | 支持重载和特化 | 仅支持特化 |
成员模板 | 无 | 可包含成员函数模板 |
通过合理选择函数模板或类模板,可以实现代码的高度复用,同时保持类型安全和性能。