当前位置: 首页 > news >正文

C++(23)—模板初阶

文章目录

  • 一、为什么需要泛型编程?
  • 二、函数模板
    • 1. 函数模板的概念
    • 2. 函数模板的语法
    • 3. 函数模板的原理
    • 4. 函数模板的实例化
    • 5. 模板参数匹配规则
  • 三、类模板
    • 1. 类模板的定义
    • 2. 类模板的实例化
  • 四、模板的底层原理
    • 1. 函数模板的编译过程
    • 2. 类模板的编译过程
  • 五、模板的优缺点
  • 六、实战示例:实现动态数组

一、为什么需要泛型编程?

在C++中,若想实现一个通用的交换函数,传统方式需要为不同类型编写多个重载函数:

void Swap(int& a, int& b) { /*...*/ }
void Swap(double& a, double& b) { /*...*/ }
void Swap(char& a, char& b) { /*...*/ }

问题:

代码冗余:仅类型不同,逻辑完全重复维护困难:新增类型需手动添加函数,易出错解决方案:泛型编程(Generic Programming)核心思想:编写与类型无关的通用代码实现工具:模板(Template)

二、函数模板

1. 函数模板的概念

函数模板是一个“蓝图”,编译器根据传入的实参类型自动生成具体函数。
示例:通用交换函数

template<typename T>
void Swap(T& a, T& b) {T tmp = a;a = b;b = tmp;
}

2. 函数模板的语法

关键字:template<typename T1, typename T2, ...>说明:typename可替换为class(但不可用struct)

3. 函数模板的原理

**编译期代码生成:**模板本身不是函数,编译器根据调用时的类型实例化具体函数。

Swap(d1, d2);  // 实例化为 void Swap(double&, double&)
Swap(i1, i2);  // 实例化为 void Swap(int&, int&)

4. 函数模板的实例化

隐式实例化
编译器自动推导类型:

Add(1, 2);      // T推导为int
Add(1.0, 2.0);  // T推导为double

显式实例化
手动指定模板参数类型:

Add<int>(1, 2.5);  // T强制为int,2.5隐式转换为int

5. 模板参数匹配规则

优先匹配普通函数:若存在同名非模板函数,优先调用它。更优匹配选择模板:若模板能生成更匹配的版本,则选择模板。
int Add(int a, int b) { return a + b; }  // 普通函数
template<typename T1, typename T2>
T1 Add(T1 a, T2 b) { return a + b; }     // 模板函数Add(1, 2);     // 调用普通函数
Add(1, 2.0);   // 调用模板生成的 Add(int, double)

三、类模板

1. 类模板的定义

类模板允许定义与类型无关的通用类,常用于容器类(如动态数组、栈、队列)。
**示例:**通用栈类

template<typename T>
class Stack {
public:Stack(size_t capacity = 4) : _array(new T[capacity]), _capacity(capacity), _size(0) {}void Push(const T& data);
private:T* _array;size_t _capacity;size_t _size;
};// 成员函数类外定义
template<typename T>
void Stack<T>::Push(const T& data) {_array[_size++] = data;  // 简化的实现(实际需处理扩容)
}

2. 类模板的实例化

显式实例化:必须指定模板参数类型

Stack<int> intStack;      // 存储int类型的栈
Stack<double> doubleStack; // 存储double类型的栈

四、模板的底层原理

1. 函数模板的编译过程

模板解析:检查模板语法是否正确。实例化:根据调用时的类型生成具体函数。编译生成代码:将实例化的函数编译为二进制指令。

2. 类模板的编译过程

模板解析:检查类模板语法。实例化:根据用户指定的类型生成具体的类。编译成员函数:按需编译成员函数(延迟实例化)。

五、模板的优缺点

优点
代码复用:一套逻辑支持多种类型。

类型安全:编译器自动检查类型错误。性能优化:生成的代码与手写代码效率相同。

缺点
编译时间增加:模板实例化会延长编译时间。

代码膨胀:多类型实例化可能导致生成代码体积增大。

六、实战示例:实现动态数组

template<typename T>
class Vector {
public:Vector() : _data(nullptr), _size(0), _capacity(0) {}void PushBack(const T& val) {if (_size == _capacity) {_capacity = _capacity == 0 ? 1 : _capacity * 2;T* newData = new T[_capacity];// 拷贝旧数据(简化实现,未处理异常)for (size_t i = 0; i < _size; ++i) {newData[i] = _data[i];}delete[] _data;_data = newData;}_data[_size++] = val;}
private:T* _data;size_t _size;size_t _capacity;
};int main() {Vector<int> intVec;intVec.PushBack(1);Vector<string> strVec;strVec.PushBack("hello");return 0;
}

相关文章:

  • java面试篇(常见的集合底层原理)
  • AI大模型之模型幻觉
  • Redis——通信协议
  • 【大模型】单选数据集制作举例
  • Java技术栈 —— 网络带宽受限,图片预览加速
  • 5.4.1 Password控件的Password属性绑定问题
  • 06 GE Modifier
  • 【AI论文】对人工智能生成文本的稳健和细粒度检测
  • 性价比超高的 英伟达Tesla T4卡 如何解决散热问题?
  • Ubuntu 22.04 更换 Nvidia 显卡后启动无法进入桌面问题的解决
  • OpenAPI 3.0学习笔记
  • 【Redis】了解Redis
  • Java Web项目(一)
  • Java29:Spring MVC
  • 积木报表查询出现jdbc.SQLServerException: 对象名 ‘user_tab_comment 的解决方法
  • Federated Weakly Supervised Video Anomaly Detection with Multimodal Prompt
  • SpringBoot集成Kafka详解
  • 【锂电池SOH估计】SVM支持向量机锂电池健康状态估计,锂电池SOH估计(Matlab完整源码和数据)
  • 零点、驻点、拐点、极值点、最值点的定义、几何意义、求解方法
  • 2025年4月19日-得物算法岗春招笔试题-第二题
  • 庆祝中国印尼建交75周年招待会暨万隆会议70周年纪念活动在京举行
  • 国开行原副行长李吉平一审获刑14年
  • 申花迎来中超三连胜,这一次终于零封对手了
  • 影子调查丨义门陈遗址建筑被“没收”风波
  • 航行警告!南海部分水域进行军事训练,禁止驶入
  • 男子拍摄女性视频后在网上配发诱导他人违法犯罪文字,已被警方行拘