📘 本篇精准集中三大核心点:C++ 函数模板基本写法、类模板实战结构,以及模板实例化和编译特性分析。以实战为导向,涵盖常用写法、典型陷阱和底层原理,为后续掌握 STL 与泛型编程打下坚实基础。
🔁 Day 4 回顾
矩点 | 记忆要点 |
---|---|
虚函数 | 运行时绑定,支持多态 |
vtable/vptr 机制 | 基于虚表进行函数调用 |
切割/析构问题 | 值传参分割字类、析构不虚导致泄露 |
RTTI/typeid | 运行时确认类型 |
dynamic_cast | 安全类型转换 |
🎯 今日目标:掌握模板机制的本质与实战技巧
- 理解函数模板、类模板的语法和用途
- 掌握模板实例化时机及编译器行为
- 引入 SFINAE 基础、默认模板参数与特化概念
- 为后续 STL 泛型开发和 C++20 concepts 做准备
🎓 核心知识点讲解
✅ 一、函数模板:一段代码打通多个类型
template<typename T>
T add(T a, T b) {
return a + b;
}
使用:
add(3, 4); // 推导为 int
add<double>(2.5, 1.7); // 显式指定为 double
📌 特点:
- 编译期生成对应类型版本,提升代码复用性
- 与内联优化结合后,效率极高
- 推导失败时报错,能提供类型安全性
📌 常见陷阱:若传入不同类型,可能推导失败,需用 T1, T2
区分
✅ 二、类模板:为类型编写类的工厂
template<typename T>
class Box {
private:
T value;
public:
Box(T val) : value(val) {}
T get() const { return value; }
void set(T val) { value = val; }
};
使用:
Box<int> intBox(42);
intBox.set(55);
Box<std::string> strBox("hello");
📌 衍生能力:类模板可嵌套类/函数模板,也可使用默认参数和偏特化
📌 注意:成员函数通常写在头文件,因类模板编译时需全部可见
✅ 三、模板实例化规则:何时生成代码?
模板只在“使用时”实例化,否则不会报错:
template<typename T>
void risky() {
int x = 1 / 0; // 编译期不会报错,除非被调用
}
📌 特点:
- 延迟实例化,减少不必要的报错与膨胀
- 适用于条件编译、选择性启用逻辑(结合 SFINAE)
✅ 四、默认模板参数与类型别名(进阶起点)
template<typename T = int>
class Counter {
T count = 0;
};
Counter<> c; // 实例化为 Counter<int>
// 类型萃取 + 别名简化
#include <type_traits>
template<typename T>
using remove_const_t = typename std::remove_const<T>::type;
📌 作用:提高模板可读性、减少冗长 typename 写法
✅ 五、SFINAE 简介:选择性启用的魔法
template<typename T>
typename std::enable_if<std::is_integral<T>::value, void>::type
process(T t) {
std::cout << "int only: " << t << std::endl;
}
📌 含义:当条件满足时生成此函数,否则该重载被忽略(替代失败但不报错)
📌 用途:
- 类型限制
- 按不同类型定制行为(int/float/std::string)
🧪 实战练习:自定义泛型容器原型
任务:基于类模板 Box 实现以下功能:
- 增加
set()
方法重置值 - 增加
print()
方法:仅当T
可用于std::cout
时才可用
提示:使用 SFINAE 控制打印是否可见
template<typename T>
class Box {
T value;
public:
Box(T v) : value(v) {}
T get() const { return value; }
void set(T v) { value = v; }
template<typename U = T>
typename std::enable_if<std::is_same<decltype(std::cout << std::declval<U>()), std::ostream&>::value>::type
print() const {
std::cout << "Box: " << value << std::endl;
}
};
🧩 总结
技术点 | 价值与说明 |
---|---|
函数模板 | 通用算法实现,提高代码复用性 |
类模板 | 泛型容器和工具类的构建基础 |
实例化机制 | 控制生成,支持延迟逻辑与优化 |
SFINAE | 提供选择性重载,简化约束写法 |
默认模板参数 | 提升接口友好性,减少使用者负担 |
📌 后续展开方向:
- 模板特化与偏特化
- C++20 Concepts 与 requires 表达式
- STL 容器与算法源码解析
- 编写类型安全的多态接口与策略类
你希望我继续撰写 Day 6 吗?或将前五天整理成博客合集/PDF 教程?我可以立即开始。