模板
975 字
5 分钟
模板
函数模板
函数模板概念
- 函数模板代表了一个函数家族
- 与类型无关,在使用时被参数化
- 根据实参类型产生函数的特定类型版本
函数模板格式
template<typename T1, typename T2, ..., typename Tn>返回值类型 函数名(参数列表) {}示例
template<typename T>void Swap(T& left, T& right) { T temp = left; left = right; right = temp;}注意
typename是用来定义模板参数的关键字- 也可以使用
class(但不能使用struct代替class)
函数模板原理
- 函数模板是一个蓝图,本身并不是函数
- 编译器根据使用方式产生特定具体类型函数的模具
- 将重复的工作交给编译器 **示例
// 编译器根据模板生成的具体函数void Swap(int& a, int& b) { // int版本 int temp = a; a = b; b = temp;}
void Swap(double& a, double& b) { // double版本 double temp = a; a = b; b = temp;}
void Swap(char& a, char& b) { // char版本 char temp = a; a = b; b = temp;}函数模板实例化
隐式实例化
让编译器根据实参推演模板参数的实际类型
template<class T>T Add(const T& left, const T& right) { return left + right;}
int main() { int a1 = 10, a2 = 20; double d1 = 10.0, d2 = 20.0;
Add(a1, a2); // T 被推演为 int Add(d1, d2); // T 被推演为 double
// Add(a1, d1); // 错误:编译器无法确定T的类型 Add(a1, (int)d1); // 解决方法1:用户自己强制转换
return 0;}显式实例化
在函数名后的 <> 中指定模板参数的实际类型
int main() { int a = 10; double b = 20.0;
// 显式实例化 Add<int>(a, b); // 指定T为int类型
return 0;}模板参数的匹配原则
原则1: 非模板函数和同名函数模板可以共存
// 专门处理int的加法函数int Add(int left, int right) { return left + right;}
// 通用加法函数模板template<class T>T Add(T left, T right) { return left + right;}
void Test() { Add(1, 2); // 调用非模板函数 Add<int>(1, 2); // 调用模板函数}原则2: 优先匹配非模板函数,除非模板能产生更好的匹配
// 专门处理int的加法函数int Add(int left, int right) { return left + right;}
// 通用加法函数模板template<class T1, class T2>T1 Add(T1 left, T2 right) { return left + right;}
void Test() { Add(1, 2); // 调用非模板函数(完全匹配) Add(1, 2.0); // 调用模板函数(生成更匹配的版本)}原则3: 模板函数不允许自动类型转换,但普通函数可以
类模板
类模板的定义格式
template<class T1, class T2, ..., class Tn>class 类模板名 { // 类内成员定义};**示例:栈类模板
#include <iostream>using namespace std;
template<typename T>class Stack {public: Stack(size_t capacity = 4) { // 构造函数 _array = new T[capacity]; // 动态分配数组 _capacity = capacity; // 设置容量 _size = 0; // 初始大小为0 }
void Push(const T& data); // 入栈函数声明
~Stack() { // 析构函数 delete[] _array; // 释放动态内存 }
private: T* _array; // 栈数据数组 size_t _capacity; // 栈容量 size_t _size; // 当前栈大小};
// 类模板成员函数定义template<class T>void Stack<T>::Push(const T& data) { // 扩容检查... // 实际需要添加扩容逻辑 _array[_size] = data; // 将数据放入栈顶 ++_size; // 栈大小增加}重要提示: 模板不建议声明和定义分离到 .h 和 .cpp 文件,会出现链接错误。
类模板的实例化
- 类模板实例化与函数模板实例化不同
- 类模板名字不是真正的类,实例化的结果才是真正的类
- 需要在类模板名字后跟
<>,将实例化的类型放在<>中
- int main() { Stack<int> st1; // Stack<int> 是类型 Stack<double> st2; // Stack<double> 是类型
return 0;}**关键区别:
Stack是类模板名Stack<int>才是具体的类型
文章分享
如果这篇文章对你有帮助,欢迎分享给更多人!
相关文章智能推荐
1
模板进阶
C/C++类型模板参数:出现在模板参数列表中,跟在class或typename后的参数类型名称 非类型模板参数:用一个常量作为类(函数)模板的参数,在模板中可将该参数当成常量使用
2
多态
C/C++多态(polymorphism):即"多种形态",指同一接口表现出不同行为的能力。
3
结构体
C/C++结构体:一些值的集合,这些值称为成员变量 每个成员可以是不同类型变量
4
类和对象
C/C++class 是定义类的关键字 类体中内容称为类的成员: 类中的变量 → 类的属性或成员变量 类中的函数 → 类的方法或成员函数 成员变量命名惯例:前面或后面加 或 m 开头(非强制) C++ 中 struct 也可以定义类,但推荐使用 c…
5
c语言字符与字符串函数
C/C++计算'\0'之前的字符个数 返回类型为sizet(无符号整型) 字符串必须以'\0'结束
随机文章随机推荐

