C++ 模板编程基础:泛型编程入门与实践
介绍 C++ 模板编程基础,涵盖函数模板与类模板的语法、实例化、特化及偏特化。内容包含类型推导规则、重载机制、编译原理及常见错误规避。通过通用链表实战案例展示模板在代码复用中的应用,并解析模板与 STL 的关联,帮助读者掌握泛型编程核心思想,提升代码灵活性与维护性。

介绍 C++ 模板编程基础,涵盖函数模板与类模板的语法、实例化、特化及偏特化。内容包含类型推导规则、重载机制、编译原理及常见错误规避。通过通用链表实战案例展示模板在代码复用中的应用,并解析模板与 STL 的关联,帮助读者掌握泛型编程核心思想,提升代码灵活性与维护性。

💡 核心重点:模板的语法规则、类型参数与非类型参数的使用、模板特化的应用场景、泛型编程的核心价值
泛型编程(Generic Programming)是一种代码复用技术,核心思想是'编写与类型无关的通用代码,在使用时再指定具体类型',实现'一次编写,多次复用'。
🗄️ 生活中的泛型类比:
在 C++ 中,若未使用模板,针对不同类型的相同逻辑需重复编写代码,导致冗余且难以维护:
// 重复代码:int 类型加法
int add_int(int a, int b) {
return a + b;
}
// 重复代码:double 类型加法
double add_double(double a, double b) {
return a + b;
}
// 重复代码:float 类型加法
float add_float(float a, float b) {
return a + b;
}
💡 模板的价值:用一套代码适配所有兼容逻辑的类型,减少冗余、提升可维护性,同时保证类型安全(编译时类型检查)。
C++ 模板主要分为两类:
✅ 核心优势:模板是 C++ 泛型编程的基础,STL(标准模板库)的容器(vector、map)、算法(sort、find)均基于模板实现。
函数模板的声明需使用 template 关键字,指定类型参数(或非类型参数),语法格式如下:
// 格式:template <模板参数列表> 返回值类型 函数名 (参数列表) { 函数体 }
template <typename T> // T 为类型参数(typename 可替换为 class,含义相同)
返回值类型 函数名 (T 参数 1, T 参数 2,...) {
// 通用逻辑(与类型无关)
}
💡 语法解析:
template <typename T>:模板声明,typename 表示'后面的标识符是类型参数',T 是类型占位符(可自定义名称,如 Type、ElemType)T 作为类型,表明参数类型由调用时指定或推导+ 运算符需确保传入类型支持该运算符)💡 示例:实现通用加法函数模板
#include <iostream>
using namespace std;
// 函数模板:通用加法函数,支持任意支持 + 运算符的类型
template <typename T> // T 为类型参数,代表任意类型
T add(T a, T b) {
cout << "模板函数调用,类型为:" << typeid(T).name() << endl;
// 打印类型名称
return a + b;
}
int main() {
// 1. 显式指定类型参数(推荐,可读性强)
int num1 = add<int>(10, 20);
cout << "int 类型加法:10 + 20 = " << num1 << endl; // 30
double num2 = add<double>(3.14, 2.86);
cout << "double 类型加法:3.14 + 2.86 = " << num2 << endl; // 6.0
// 2. 隐式推导类型参数(编译器根据实参类型自动推导 T)
float num3 = add(5.5f, 3.5f);
cout << "float 类型加法:5.5 + 3.5 = " << num3 << endl; // 9.0f
string str1 = "Hello, ", str2 = "C++!";
string str3 = add(str1, str2); // 字符串支持 + 运算符,推导 T 为 string
cout << "string 类型加法:" << str3 << endl; // Hello, C++!
return 0;
}
✅ 运行结果:
模板函数调用,类型为:int int 类型加法:10 + 20 = 30
模板函数调用,类型为:double double 类型加法:3.14 + 2.86 = 6
模板函数调用,类型为:float float 类型加法:5.5 + 3.5 = 9
模板函数调用,类型为:std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > string 类型加法:Hello, C++!
编译器会根据实参类型自动推导模板的类型参数 T,推导规则如下:
T 类型),否则推导失败💡 示例:类型推导细节
template <typename T>
void print_type(T param) {
cout << "参数类型:" << typeid(T).name() << endl;
}
int main() {
int a = 10;
const int b = 20;
int& c = a;
int arr[5] = {1, 2, 3, 4, 5};
void func(int) {}
print_type(a); // 实参为 int,推导 T=int
print_type(b); // 实参为 const int,推导 T=int(const 被忽略,param 为 int)
print_type(c); // 实参为 int&,推导 T=int(引用被忽略,param 为 int)
print_type(arr); // 实参数组,推导 T=int*(数组退化为指针)
print_type(func); // 实参函数,推导 T=void(*)(int)(函数退化为指针)
// 若需保留引用/const,需显式指定模板参数为引用类型
template <typename T>
void print_ref_type(T& param) {}
print_ref_type(b); // 推导 T=const int(保留 const)
print_ref_type(c); // 推导 T=int(保留引用,param 为 int&)
return 0;
}
⚠️ 警告:若实参类型不一致且未显式指定类型,会导致编译错误:
// 错误:实参类型分别为 int 和 double,T 无法推导
add(10, 3.14); // 编译错误:no matching function for call to 'add(int, double)'
// 解决:显式指定类型,编译器会进行隐式类型转换(若支持)
add<double>(10, 3.14); // 正确,10 被转换为 double 类型
函数模板支持重载,可与普通函数或其他函数模板构成重载关系,调用时遵循'最匹配原则':
💡 示例:函数模板重载
#include <iostream>
using namespace std;
// 普通函数:处理 int 类型加法
int add(int a, int b) {
cout << "普通函数(int)调用:";
return a + b;
}
// 函数模板:通用加法
template <typename T>
T add(T a, T b) {
cout << "模板函数(" << typeid(T).name() << ")调用:";
return a + b;
}
// 函数模板重载:支持两个不同类型的参数
template <typename T1, typename T2>
auto add(T1 a, T2 b) -> decltype(a + b) {
// 尾置返回类型,推导返回值类型
cout << "模板函数(" << typeid(T1).name() << "," << typeid(T2).name() << ")调用:";
return a + b;
}
int main() {
// 调用普通函数(完全匹配 int 类型)
cout << add(10, 20) << endl; // 输出:普通函数(int)调用:30
// 调用通用模板函数(double 类型匹配)
cout << add(3.14, 2.86) << endl; // 输出:模板函数(double)调用:6
// 调用重载模板函数(int 和 double 类型不同)
cout << add(10, 3.14) << endl; // 输出:模板函数(int,double)调用:13.14
return 0;
}
✅ 运行结果:
普通函数(int)调用:30
模板函数(double)调用:6
模板函数(int,double)调用:13.14
当通用模板无法满足特定类型的需求(如特殊逻辑、运算符不支持)时,可对模板进行特化(Specialization),为特定类型提供专属实现。
template <> // 空模板参数列表,表示特化
返回值类型 函数名<特化类型>(特化类型 参数 1, 特化类型 参数 2,...) {
// 专属逻辑
}
💡 示例:函数模板特化(处理 string 类型的特殊加法)
#include <iostream>
#include <string>
using namespace std;
// 通用函数模板:加法
template <typename T>
T add(T a, T b) {
cout << "通用模板:";
return a + b;
}
// 特化:为 string 类型提供专属实现(拼接字符串时添加空格)
template <>
string add<string>(string a, string b) {
cout << "string 特化模板:";
return a + " " + b; // 特殊逻辑:拼接时添加空格
}
int main() {
cout << add(10, 20) << endl; // 通用模板:30
cout << add(3.14, 2.86) << endl; // 通用模板:6
cout << add(string("Hello"), string("World")) << endl; // string 特化模板:Hello World
return 0;
}
✅ 运行结果:
通用模板:30
通用模板:6
string 特化模板:Hello World
⚠️ 注意事项:
类模板用于创建通用类,支持不同类型的成员变量和成员函数参数,语法格式如下:
template <typename T> // 模板参数列表(可多个类型参数)
class 类名 {
public:
// 成员变量(类型为 T)
T 成员变量;
// 构造函数
类名 (T 参数): 成员变量 (参数) {}
// 成员函数(参数/返回值类型可使用 T)
T get_value() const {
return 成员变量;
}
void set_value(T value) {
成员变量 = value;
}
};
💡 语法解析:
class 关键字前加 template <模板参数列表>T 定义成员变量、成员函数参数或返回值类模板不能直接使用,需实例化(指定具体类型)后才能创建对象,实例化分为显式实例化和隐式实例化。
💡 示例:类模板的定义与实例化
#include <iostream>
using namespace std;
// 类模板:通用容器类(存储单个元素)
template <typename T>
class Container {
private:
T data; // 成员变量,类型为 T
public:
// 构造函数
Container(T value): data(value) {}
// 成员函数:类内定义
T get_data() const {
return data;
}
// 成员函数:类外定义(需再次声明模板参数)
void set_data(T value);
};
// 类外定义成员函数:必须加 template <typename T>
template <typename T>
void Container<T>::set_data(T value) {
data = value;
}
int main() {
// 1. 显式实例化(推荐,可读性强)
Container<int> int_container(100);
cout << "int 容器初始值:" << int_container.get_data() << endl; // 100
int_container.set_data(200);
cout << "int 容器修改后:" << int_container.get_data() << endl; // 200
// 2. 隐式实例化(编译器根据构造函数参数推导类型)
Container<double> double_container(3.14);
cout << "double 容器值:" << double_container.get_data() << endl; // 3.14
// 3. 实例化不同类型的对象(相互独立)
Container<string> str_container("Hello C++");
cout << "string 容器值:" << str_container.get_data() << endl; // Hello C++
return 0;
}
✅ 运行结果:
int 容器初始值:100
int 容器修改后:200
double 容器值:3.14
string 容器值:Hello C++
类模板支持多个类型参数(或非类型参数),参数之间用逗号分隔:
// 多类型参数:T 为元素类型,Alloc 为分配器类型(默认值为 void)
template <typename T, typename Alloc = void>
class MyVector {
// 类实现
};
// 非类型参数:N 为常量整数(必须是编译期可确定的值)
template <typename T, int N>
class Array {
private:
T data[N]; // 固定大小的数组,N 为模板参数
public:
int size() const {
return N;
}
T& operator[](int index) {
return data[index];
}
};
💡 示例:带非类型参数的类模板(固定大小数组)
#include <iostream>
using namespace std;
// 类模板:固定大小数组(N 为非类型参数,编译期确定大小)
template <typename T, int N>
class FixedArray {
private:
T data[N]; // 数组大小为 N(编译期固定)
public:
// 构造函数:初始化所有元素为默认值
FixedArray() {
for (int i = 0; i < N; ++i) {
data[i] = T(); // T() 为默认构造(如 int 默认 0,string 默认空串)
}
}
// 赋值操作:设置指定索引的元素
void set(int index, T value) {
if (index >= 0 && index < N) {
data[index] = value;
}
}
// 获取元素
T get(int index) const {
if (index >= 0 && index < N) {
return data[index];
}
return T(); // 索引越界返回默认值
}
// 获取数组大小
int size() const {
return N;
}
// 打印数组
void print() const {
for (int i = 0; i < N; ++i) {
cout << data[i] << " ";
}
cout << endl;
}
};
int main() {
// 实例化:int 类型,大小为 5 的数组
FixedArray<int, 5> int_arr;
int_arr.set(0, 10);
int_arr.set(1, 20);
int_arr.set(2, 30);
cout << "int 数组(大小" << int_arr.size() << "):";
int_arr.print(); // 10 20 30 0 0
// 实例化:double 类型,大小为 3 的数组
FixedArray<double, 3> double_arr;
double_arr.set(0, 1.1);
double_arr.set(1, 2.2);
double_arr.set(2, 3.3);
cout << "double 数组(大小" << double_arr.size() << "):";
double_arr.print(); // 1.1 2.2 3.3
// 实例化:string 类型,大小为 4 的数组
FixedArray<string, 4> str_arr;
str_arr.set(0, "Apple");
str_arr.set(1, "Banana");
cout << "string 数组(大小" << str_arr.size() << "):";
str_arr.print(); // Apple Banana (后两个为默认空串)
return 0;
}
✅ 运行结果:
int 数组(大小 5):10 20 30 0 0
double 数组(大小 3):1.1 2.2 3.3
string 数组(大小 4):Apple Banana
⚠️ 非类型参数的限制:
类模板同样支持特化(为特定类型提供专属实现),且支持偏特化(为部分模板参数指定类型,保留其他参数的通用性)。
全特化是为所有模板参数指定具体类型,语法格式:
template <> // 空模板参数列表
class 类名<特化类型> {
// 专属实现
};
💡 示例:类模板全特化
#include <iostream>
#include <string>
using namespace std;
// 通用类模板:打印元素类型和值
template <typename T>
class Printer {
public:
void print(T value) {
cout << "通用模板 - 类型:" << typeid(T).name() << ",值:" << value << endl;
}
};
// 全特化:为 string 类型提供专属实现(美化输出)
template <>
class Printer<string> {
public:
void print(string value) {
cout << "string 特化模板 - 字符串:\"" << value << "\"" << endl;
}
};
// 全特化:为 int 类型提供专属实现(添加单位)
template <>
class Printer<int> {
public:
void print(int value) {
cout << "int 特化模板 - 整数:" << value << "(单位:个)" << endl;
}
};
int main() {
Printer<double> double_printer;
double_printer.print(3.14); // 通用模板 - 类型:double,值:3.14
Printer<string> str_printer;
str_printer.print("Hello C++"); // string 特化模板 - 字符串:"Hello C++"
Printer<int> int_printer;
int_printer.print(100); // int 特化模板 - 整数:100(单位:个)
return 0;
}
✅ 运行结果:
通用模板 - 类型:double,值:3.14
string 特化模板 - 字符串:"Hello C++"
int 特化模板 - 整数:100(单位:个)
偏特化是为部分模板参数指定类型,保留其他参数的通用性,适用于多参数模板。语法格式:
template <保留的模板参数>
class 类名<保留参数,指定的参数> {
// 偏特化实现
};
💡 示例:类模板偏特化
#include <iostream>
using namespace std;
// 多参数类模板:T 为元素类型,U 为附加类型
template <typename T, typename U>
class Pair {
public:
Pair(T first, U second): first_val(first), second_val(second) {}
void display() {
cout << "通用模板 - 第一个值(" << typeid(T).name() << "):" << first_val << ",第二个值(" << typeid(U).name() << "):" << second_val << endl;
}
private:
T first_val;
U second_val;
};
// 偏特化 1:当第二个参数 U 为 int 时的专属实现
template <typename T> // 保留第一个参数 T,指定第二个参数为 int
class Pair<T, int> {
public:
Pair(T first, int second): first_val(first), second_val(second) {}
void display() {
cout << "偏特化(U=int) - 第一个值:" << first_val << ",第二个值(整数):" << second_val << "(已乘以 2:" << second_val * 2 << ")" << endl;
}
private:
T first_val;
int second_val;
};
// 偏特化 2:当两个参数均为指针类型时的专属实现
template <typename T, typename U>
class Pair<T*, U*> {
// 两个参数均为指针类型
public:
Pair(T* first, U* second): first_ptr(first), second_ptr(second) {}
void display() {
cout << "偏特化(T*+U*) - 第一个指针地址:" << first_ptr << ",值:" << *first_ptr << ";第二个指针地址:" << second_ptr << ",值:" << *second_ptr << endl;
}
private:
T* first_ptr;
U* second_ptr;
};
int main() {
// 通用模板:T=string,U=double
Pair<string, double> p1("PI", 3.14);
p1.display();
// 偏特化 1:T=string,U=int
Pair<string, int> p2("计数", 5);
p2.display();
// 偏特化 2:T=int*,U=double*
int a = 10;
double b = 2.5;
Pair<int*, double*> p3(&a, &b);
p3.display();
return 0;
}
✅ 运行结果:
通用模板 - 第一个值(std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >):PI,第二个值(double):3.14
偏特化(U=int) - 第一个值:计数,第二个值(整数):5(已乘以 2:10)
偏特化(T*+U*) - 第一个指针地址:0x7ffee4b7e7ac,值:10;第二个指针地址:0x7ffee4b7e7a0,值:2.5
⚠️ 偏特化注意事项:
C++ 模板采用'实例化时编译'(Compile on Instantiation)机制,核心特点:
💡 编译流程解析:
add<int>(10,20)),编译器会生成 int 类型的 add 函数代码⚠️ 常见错误:模板定义与声明分离导致链接错误
// 错误示例:
// add.h(模板声明)
template <typename T> T add(T a, T b);
// add.cpp(模板定义)
template <typename T> T add(T a, T b) {
return a + b;
}
// main.cpp(调用模板)
#include "add.h"
int main() {
add<int>(10, 20); // 链接错误:undefined reference to `int add<int>(int, int)`
}
// add.cpp
template <typename T> T add(T a, T b) {
return a + b;
}
// 显式实例化 int 和 double 类型
template int add<int>(int, int);
template double add<double>(double, double);
原因:实参类型不一致、模板参数无法从实参推导、隐式转换不支持。
规避方案:
// 错误:实参类型不一致,推导失败
add(10, 3.14);
// 正确:显式指定类型
add<double>(10, 3.14);
// 正确:手动转换实参类型
add(static_cast<double>(10), 3.14);
原因:传入的类型不支持模板中的运算符或函数(如对自定义类使用 + 运算符)。
规避方案:
concept)// 自定义类
class Point {
public:
int x, y;
Point(int x = 0, int y = 0): x(x), y(y) {}
// 重载 + 运算符,支持模板中的加法操作
Point operator+(const Point& other) {
return Point(x + other.x, y + other.y);
}
};
// 模板可正常处理 Point 类型
Point p1(1, 2), p2(3, 4);
Point p3 = add(p1, p2); // 正确,p3=(4,6)
原因:非类型参数使用了运行时才能确定的值(如普通变量)。
规避方案:
// 错误:n 是运行时变量,不能作为非类型参数
int n = 5;
FixedArray<int, n> arr; // 编译错误:non-type template argument is not a constant expression
// 正确:使用 const 常量(编译期确定)
const int N = 5;
FixedArray<int, N> arr;
原因:特化模板的函数名、参数列表与通用模板不一致。
规避方案:
// 通用模板
template <typename T> T add(T a, T b) {
return a + b;
}
// 错误:特化模板参数列表与通用模板不一致(多了一个参数)
template <>
int add<int>(int a, int b, int c) {
return a + b + c;
}
实现一个通用单向链表类,支持任意类型的元素存储,提供插入、删除、查找、遍历等基础操作,通过模板实现类型无关性。
ListNode<T>,存储 T 类型的元素和下一个节点的指针LinkedList<T>,包含头节点指针、链表长度等成员,实现核心操作#include <iostream>
#include <string>
using namespace std;
// 1. 链表节点类模板
template <typename T>
class ListNode {
public:
T data; // 节点数据(通用类型 T)
ListNode<T>* next; // 下一个节点指针
// 构造函数
ListNode(T value): data(value), next(nullptr) {}
};
// 2. 链表类模板
template <typename T>
class LinkedList {
private:
ListNode<T>* head; // 头节点指针
int length; // 链表长度
public:
// 构造函数:初始化空链表
LinkedList(): head(nullptr), length(0) {}
// 析构函数:释放所有节点内存
~LinkedList() {
ListNode<T>* curr = head;
while (curr != nullptr) {
ListNode<T>* temp = curr;
curr = curr->next;
delete temp;
}
head = nullptr;
length = 0;
}
// 头插法:在链表头部插入元素
void push_front(T value) {
ListNode<T>* new_node = new ListNode<T>(value);
new_node->next = head;
head = new_node;
length++;
}
// 尾插法:在链表尾部插入元素
void push_back(T value) {
ListNode<T>* new_node = new ListNode<T>(value);
if (head == nullptr) { // 空链表,新节点作为头节点
head = new_node;
} else { // 找到尾节点
ListNode<T>* curr = head;
while (curr->next != nullptr) {
curr = curr->next;
}
curr->next = new_node;
}
length++;
}
// 按索引插入元素(索引从 0 开始)
bool insert(int index, T value) {
if (index < 0 || index > length) { // 索引非法
cout << "插入失败:索引" << index << "非法!" << endl;
return false;
}
if (index == 0) { // 索引 0,等价于头插法
push_front(value);
return true;
}
// 找到索引前一个节点
ListNode<T>* curr = head;
for (int i = 0; i < index - 1; ++i) {
curr = curr->next;
}
ListNode<T>* new_node = new ListNode<T>(value);
new_node->next = curr->next;
curr->next = new_node;
length++;
return true;
}
// 按值删除第一个匹配的元素
bool remove(T value) {
if (head == nullptr) { // 空链表
cout << "删除失败:链表为空!" << endl;
return false;
}
ListNode<T>* curr = head;
ListNode<T>* prev = nullptr;
// 查找目标元素
while (curr != nullptr && curr->data != value) {
prev = curr;
curr = curr->next;
}
if (curr == nullptr) { // 未找到元素
cout << "删除失败:未找到值" << value << "!" << endl;
return false;
}
// 删除节点
if (prev == nullptr) { // 删除头节点
head = curr->next;
} else { // 删除中间/尾节点
prev->next = curr->next;
}
delete curr;
length--;
return true;
}
// 按索引查找元素
T get(int index) const {
if (index < 0 || index >= length) {
cout << "查找失败:索引" << index << "非法!" << endl;
return T(); // 返回默认值
}
ListNode<T>* curr = head;
for (int i = 0; i < index; ++i) {
curr = curr->next;
}
return curr->data;
}
// 获取链表长度
int size() const {
return length;
}
// 遍历打印链表(通用版本)
void print() const {
if (head == nullptr) {
cout << "链表为空!" << endl;
return;
}
cout << "链表元素(长度" << length << "):";
ListNode<T>* curr = head;
while (curr != nullptr) {
cout << curr->data << " -> ";
curr = curr->next;
}
cout << "nullptr" << endl;
}
};
// 3. 特化:为 string 类型提供专属 print 函数(美化输出)
template <>
void LinkedList<string>::print() const {
if (head == nullptr) {
cout << "链表为空!" << endl;
return;
}
cout << "字符串链表(长度" << length << "):";
ListNode<string>* curr = head;
while (curr != nullptr) {
cout << "\"" << curr->data << "\" -> ";
curr = curr->next;
}
cout << "nullptr" << endl;
}
// 测试代码
int main() {
// 测试 int 类型链表
cout << "===== 测试 int 类型链表 =====" << endl;
LinkedList<int> int_list;
int_list.push_back(10);
int_list.push_back(20);
int_list.push_front(5);
int_list.insert(2, 15); // 在索引 2 插入 15
int_list.print(); // 输出:链表元素(长度 4):5 -> 10 -> 15 -> 20 -> nullptr
cout << "索引 2 的元素:" << int_list.get(2) << endl; // 15
int_list.remove(10); // 删除值 10
int_list.print(); // 输出:链表元素(长度 3):5 -> 15 -> 20 -> nullptr
// 测试 string 类型链表(特化 print)
cout << "\n===== 测试 string 类型链表 =====" << endl;
LinkedList<string> str_list;
str_list.push_back("Apple");
str_list.push_back("Banana");
str_list.push_front("Orange");
str_list.insert(1, "Grape");
str_list.print(); // 输出:字符串链表(长度 4):"Orange" -> "Grape" -> "Apple" -> "Banana" -> nullptr
str_list.remove("Grape");
str_list.print(); // 输出:字符串链表(长度 3):"Orange" -> "Apple" -> "Banana" -> nullptr
// 测试 double 类型链表
cout << "\n===== 测试 double 类型链表 =====" << endl;
LinkedList<double> double_list;
double_list.push_back(1.1);
double_list.push_back(2.2);
double_list.push_front(0.5);
double_list.print(); // 输出:链表元素(长度 3):0.5 -> 1.1 -> 2.2 -> nullptr
return 0;
}
===== 测试 int 类型链表 =====
链表元素(长度 4):5 -> 10 -> 15 -> 20 -> nullptr
索引 2 的元素:15
链表元素(长度 3):5 -> 15 -> 20 -> nullptr
===== 测试 string 类型链表 =====
字符串链表(长度 4):"Orange" -> "Grape" -> "Apple" -> "Banana" -> nullptr
字符串链表(长度 3):"Orange" -> "Apple" -> "Banana" -> nullptr
===== 测试 double 类型链表 =====
链表元素(长度 3):0.5 -> 1.1 -> 2.2 -> nullptr
✅ 结论:通过模板实现的通用链表支持 int、string、double 等多种类型,代码复用率高,且通过特化为 string 类型提供了美化输出,兼顾了通用性和灵活性。实际开发中,类似 STL 的 vector、list 等容器均采用类似的模板设计。
STL(Standard Template Library,标准模板库)是 C++ 泛型编程的典范,其核心组件(容器、算法、迭代器)均基于模板实现:
💡 示例:STL 模板的使用(vector 容器+sort 算法)
#include <iostream>
#include <vector>
#include <algorithm> // 包含 sort 算法
using namespace std;
int main() {
// vector<int>:类模板实例化,存储 int 类型
vector<int> nums = {5, 2, 9, 1, 5, 6};
// sort 算法:函数模板,作用于 vector 容器
sort(nums.begin(), nums.end()); // 升序排序
cout << "排序后的 vector:";
for (int num : nums) {
cout << num << " ";
}
cout << endl; // 输出:1 2 5 5 6 9
// vector<string>:实例化存储 string 类型
vector<string> fruits = {"Apple", "Banana", "Orange", "Grape"};
sort(fruits.begin(), fruits.end()); // 字符串按字典序排序
cout << "排序后的 string vector:";
for (const string& fruit : fruits) {
cout << fruit << " ";
}
cout << endl; // 输出:Apple Banana Grape Orange
return 0;
}
✅ 核心启示:模板是 STL 的基础,掌握模板编程后,能更深入理解 STL 的设计思想,甚至自定义适配 STL 的容器或算法。
通过本文学习,你应能独立编写函数模板和类模板,解决实际开发中的代码复用问题,并理解模板特化、偏特化等高级技术的应用场景。下一篇将深入探讨 C++ 的异常处理机制,提升代码的健壮性和容错能力!

微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online
将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML 转 Markdown 互为补充。 在线工具,Markdown 转 HTML在线工具,online
将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML 转 Markdown在线工具,online
通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online