模板是 C++ 中的一种通用编程技术,允许函数或类在定义时不具体指定数据类型,而是在使用时根据实际类型实例化。模板使代码更加灵活且可重用,是泛型编程(Generic Programming)的核心。
在编写函数或类时,如果需要支持多种数据类型,通常会编写多个版本的代码,导致代码冗余且难以维护。模板提供了一种更优雅的解决方案,通过定义一次模板,可以支持多种数据类型。
#include
using namespace std;
int add(int a, int b) {
return a + b;
}
double add(double a, double b) {
return a + b;
}
int main() {
cout << add(3, 4) << endl; // 调用 int 版本
cout << add(3.5, 4.5) << endl; // 调用 double 版本
return 0;
}
#include
using namespace std;
template
T add(T a, T b) {
return a + b;
}
int main() {
cout << add(3, 4) << endl; // 实例化 int 版本
cout << add(3.5, 4.5) << endl; // 实例化 double 版本
return 0;
}
输出
7
8
说明:
函数模板用于定义能够处理不同数据类型的函数。
template
返回类型 函数名(参数列表) {
// 函数体
}
template
:定义模板的关键字。
:模板参数,T
是占位符,可以用任何合法的标识符代替。T
:表示函数的参数和返回值类型。#include
using namespace std;
template
T maxOf(T a, T b) {
return (a > b) ? a : b;
}
int main() {
cout << "Max of 10 and 20: " << maxOf(10, 20) << endl; // 实例化为 int
cout << "Max of 3.5 and 2.7: " << maxOf(3.5, 2.7) << endl; // 实例化为 double
cout << "Max of 'A' and 'Z': " << maxOf('A', 'Z') << endl; // 实例化为 char
return 0;
}
输出
Max of 10 and 20: 20
Max of 3.5 and 2.7: 3.5
Max of 'A' and 'Z': Z
函数模板可以支持多个模板参数。
#include
using namespace std;
template
void display(T1 a, T2 b) {
cout << "First: " << a << ", Second: " << b << endl;
}
int main() {
display(10, 20.5); // T1 为 int,T2 为 double
display("Hello", 100); // T1 为 const char*,T2 为 int
return 0;
}
输出
First: 10, Second: 20.5
First: Hello, Second: 100
#include
using namespace std;
template
T square(T x) {
return x * x;
}
int main() {
cout << square(5) << endl; // 自动推导为 int
cout << square(5.5) << endl; // 显式实例化为 double
return 0;
}
输出
25
30.25
类模板用于定义能够处理不同数据类型的类。
template
class 类名 {
public:
T 数据成员;
类名(T 参数) : 数据成员(参数) {}
void display() {
cout << 数据成员 << endl;
}
};
#include
using namespace std;
template
class Box {
private:
T value;
public:
Box(T val) : value(val) {}
void display() {
cout << "Value: " << value << endl;
}
};
int main() {
Box intBox(100); // 实例化为 int
Box doubleBox(3.14); // 实例化为 double
intBox.display();
doubleBox.display();
return 0;
}
输出
Value: 100
Value: 3.14
类模板也可以支持多个模板参数。
#include
using namespace std;
template
class Pair {
private:
T1 first;
T2 second;
public:
Pair(T1 a, T2 b) : first(a), second(b) {}
void display() {
cout << "First: " << first << ", Second: " << second << endl;
}
};
int main() {
Pair p1(10, 3.14); // T1 为 int,T2 为 double
Pair p2("Age", 25); // T1 为 string,T2 为 int
p1.display();
p2.display();
return 0;
}
输出
First: 10, Second: 3.14
First: Age, Second: 25
模板特化允许为特定的数据类型提供专门的实现,而其他类型仍然使用通用模板。
针对某种特定类型提供完全不同的实现。
#include
using namespace std;
template
T maxOf(T a, T b) {
return (a > b) ? a : b;
}
// 特化版本
template <>
const char* maxOf(const char* a, const char* b) {
return (strcmp(a, b) > 0) ? a : b;
}
int main() {
cout << maxOf(10, 20) << endl; // 使用通用模板
cout << maxOf("apple", "orange") << endl; // 使用特化版本
return 0;
}
输出
20
orange
偏特化允许对模板的部分参数进行特化。
#include
using namespace std;
// 通用模板
template
class Pair {
public:
void display() {
cout << "Generic template" << endl;
}
};
// 偏特化:当两个参数类型相同时
template
class Pair {
public:
void display() {
cout << "Specialized template for same types" << endl;
}
};
int main() {
Pair p1;
Pair p2;
p1.display(); // 通用模板
p2.display(); // 特化模板
return 0;
}
输出
Generic template
Specialized template for same types
std::vector
、std::map
等。std::sort
、std::find
等。通过模板,C++ 提供了强大的泛型编程能力,极大地提高了代码的可复用性和灵活性,同时保持了类型安全性。
在之前的内容中,我们学习了 C++ 模板的基本使用,包括函数模板、类模板以及模板特化等内容。在本节中,我们将进一步探讨模板的高级功能和实际应用,包括模板的递归、模板元编程、可变参数模板以及模板与 STL 的结合。
模板递归是一种强大的技术,允许通过递归模板的方式来完成编译时计算(如阶乘、斐波那契数等)。
#include
using namespace std;
// 基本模板
template
struct Factorial {
static const int value = N * Factorial::value; // 递归调用
};
// 特化模板(递归终止条件)
template <>
struct Factorial<0> {
static const int value = 1;
};
int main() {
cout << "Factorial of 5: " << Factorial<5>::value << endl; // 计算 5!
cout << "Factorial of 10: " << Factorial<10>::value << endl; // 计算 10!
return 0;
}
输出
Factorial of 5: 120
Factorial of 10: 3628800
说明:
Factorial<5>::value
表示 5!,通过模板递归计算得出。#include
using namespace std;
// 基本模板
template
struct Fibonacci {
static const int value = Fibonacci::value + Fibonacci::value;
};
// 特化模板(递归终止条件)
template <>
struct Fibonacci<0> {
static const int value = 0;
};
template <>
struct Fibonacci<1> {
static const int value = 1;
};
int main() {
cout << "Fibonacci(10): " << Fibonacci<10>::value << endl; // 计算第 10 项
cout << "Fibonacci(15): " << Fibonacci<15>::value << endl; // 计算第 15 项
return 0;
}
输出
Fibonacci(10): 55
Fibonacci(15): 610
模板元编程(TMP)是一种使用模板在编译时完成计算的编程技术,广泛用于优化代码和生成复杂的编译时逻辑。
通过模板实现类似 if-else
的编译时分支判断。
#include
using namespace std;
// 判断是否为偶数
template
struct IsEven {
static const bool value = (N % 2 == 0); // 编译时计算
};
int main() {
cout << "Is 4 even? " << (IsEven<4>::value ? "Yes" : "No") << endl;
cout << "Is 7 even? " << (IsEven<7>::value ? "Yes" : "No") << endl;
return 0;
}
输出
Is 4 even? Yes
Is 7 even? No
通过模板递归计算数组的最大值。
#include
using namespace std;
// 获取最大值
template
struct Max {
static const int value = (A > B) ? A : B;
};
int main() {
cout << "Max of 10 and 20: " << Max<10, 20>::value << endl;
cout << "Max of 42 and 15: " << Max<42, 15>::value << endl;
return 0;
}
输出
Max of 10 and 20: 20
Max of 42 and 15: 42
C++11 引入了可变参数模板,允许模板接受任意数量的模板参数。这大大增强了模板的灵活性。
#include
using namespace std;
// 基本模板:递归终止
void print() {
cout << endl;
}
// 可变参数模板
template
void print(T first, Args... rest) {
cout << first << " ";
print(rest...); // 递归调用
}
int main() {
print(1, 2.5, "Hello", 'A'); // 打印多种类型的参数
return 0;
}
输出
1 2.5 Hello A
说明:
Args... rest
表示可变参数包。通过可变参数模板计算任意数量参数的总和。
#include
using namespace std;
// 递归终止
template
T sum(T value) {
return value;
}
// 可变参数模板
template
T sum(T first, Args... rest) {
return first + sum(rest...); // 递归计算
}
int main() {
cout << "Sum: " << sum(1, 2, 3, 4, 5) << endl; // 求和
cout << "Sum: " << sum(10.5, 20.3, 30.2) << endl;
return 0;
}
输出
Sum: 15
Sum: 61
标准模板库(STL)是 C++ 模板的经典应用。STL 提供了通用的容器类和算法,通过模板实现了高度的复用性和灵活性。
STL 容器(如 std::vector
)通过模板支持任意类型的数据。
#include
#include
using namespace std;
template
void displayVector(const vector& vec) {
for (const T& val : vec) {
cout << val << " ";
}
cout << endl;
}
int main() {
vector intVec = {1, 2, 3, 4};
vector strVec = {"Hello", "World"};
displayVector(intVec);
displayVector(strVec);
return 0;
}
输出
1 2 3 4
Hello World
模板允许为 STL 容器提供自定义的比较逻辑。
#include
#include
using namespace std;
// 自定义比较函数
struct Compare {
bool operator()(int a, int b) const {
return a > b; // 降序排列
}
};
int main() {
set mySet = {3, 1, 4, 1, 5, 9};
for (int val : mySet) {
cout << val << " ";
}
return 0;
}
输出
9 5 4 3 1
模板可以与现代 C++ 特性(如类型推导、智能指针等)结合,编写更优雅的代码。
C++14 引入了自动返回值推导,简化了模板的定义。
#include
using namespace std;
template
auto add(T1 a, T2 b) {
return a + b; // 自动推导返回值类型
}
int main() {
cout << add(3, 4.5) << endl;
return 0;
}
输出
7.5
通过模板,C++ 实现了极高的灵活性和性能,是语言的一大特色。在实际项目中,模板广泛应用于泛型库(如 STL)、编译时优化以及复杂算法的实现,极大地提高了编程效率和代码质量。