【C++】模板

article/2025/6/23 10:47:09

目录

1、函数模板

基本用法

函数模板的实现原理

函数模板的实例化

模板参数的匹配原则

2、类模板

类模板的定义格式

类模板的实例化


1、函数模板

基本用法

template < typename T >返回值类型 函数名(参数列表){}

template 是模板的意思,typename是用来定义模板参数关键字(也可以是 class),T 是模板参数。

可以一次性定义多个模板参数

template<typename T1, typename T2,......,typename Tn>

T1、T2 实例化后的实际类型可以相同,也可以不同。 

模板参数也可以作为返回值。

示例:

 template<typename T>void Swap( T& left,  T& right){T temp = left;left = right;right = temp;}

函数模板的实现原理

函数模板是一个蓝图,它本身不是函数,是编译器用使用方式产生特定具体类型函数的模具。所以其实模板就是将本来应该我们做的重复的事情交给了编译器

函数模板的实例化

在编译器编译阶段,对于模板函数的使用,编译器需要根据传入的实参类型来推演生成对应类型的函数以供调用。比如:当用double类型使用函数模板时,编译器通过对实参类型的推演,将T确定为double类型,然后产生一份专门处理double类型的代码,对于自定义类型(类)、指针类型也是如此。

模板参数实例化分为:隐式实例化和显式实例化

1. 隐式实例化:让编译器根据实参推演模板参数的实际类型。

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);Add(d1, d2);Add(a1, d1);/*Add(a1, d1);不能通过编译,因为在编译期间,当编译器看到该实例化时,需要推演其实参类型通过实参a1将T推演为int,通过实参d1将T推演为double类型,但模板参数列表中只有一个T,编译器无法确定此处到底该将T确定为int 或者 double类型而报错注意:在模板中,编译器一般不会进行类型转换操作,因为一旦转化出问题,编译器就需要背黑锅Add(a1, d1);*/// 此时有两种处理方式://1. 用户自己来强制转化 Add(a1, (int)d1);Add((double)a,d1);//2. 使用显式实例化Add<int>(a1,b1);// b1 隐式类型转换Add<double>(a1,b1);// a1 隐式类型转换

不管是隐式类型转换还是显式类型转换都会产生临时变量,临时变量具有常性,要传递给常引用的函数参数(const 类型名&) 

也就是说,Add 函数的形参不能写成:

template<class T>T Add(T& left, T& right){return left + right;}

2. 显式实例化:在函数名后的<>中指定模板参数的实际类型

 int main(){int a = 10;double b = 20.0;// 显式实例化Add<int>(a, b);return 0;}

使用显式实例化的场景:

template<class T> T* Alloc(int n)
{return new T[n];
}int main()
{double* p = Alloc<double>(10);return 0;
}

 函数模板在类内声明,在类外定义时仍要加 template< typename T>:

模板参数的匹配原则

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);  // 调用编译器实例化的Add版本       }

2. 对于非模板函数和同名函数模板,如果其他条件都相同,在调动时会优先调用非模板函数而不会从该模 板产生出一个实例。如果模板可以产生一个具有更好匹配的函数, 那么将选择模板

 void Test(){Add(1, 2);     // 与非函数模板类型完全匹配,不需要函数模板实例化Add(1, 2.0);   // 模板函数可以生成更加匹配的版本,编译器根据实参生成更加匹配的函数  
}

2、类模板

类模板的定义格式

template<class T1, class T2, ..., class Tn> 
class 类模板名
{// 类内成员定义
};    

示例:

// 动态顺序表
// 注意:Vector不是具体的类,是编译器根据被实例化的类型生成具体类的模具
template<class T>class Vector{ 
public :Vector(size_t capacity = 10): _pData(new T[capacity]),  _size(0),  _capacity(capacity){}// 使用析构函数演示:模板函数在类中声明,在类外定义。~Vector();void PushBack(const T& data);void PopBack();// ...size_t Size() {return _size;}T& operator[](size_t pos){assert(pos < _size);return _pData[pos];}private:T* _pData;size_t _size;size_t _capacity;};

类模板函数在类内声明,在类外定义 

// 注意:类模板中函数放在类外进行定义时,需要加模板参数列表
template <class T>
Vector<T>::~Vector()
{if(_pData)delete[] _pData;_size = _capacity = 0;
}

对于普通的类,类名就是类型(如 Date 类,类名是 Date,类型名也是 Date),对于类模板,类名(模板名)不是类型(如上面的 Vector ,类名是 Vector,但类型名不是 Vector),类型名是 vector<T>(如 Vector< int >),在使用 :: 指定访问的域时,:: 左边必须是类型名( Vector<T>::~Vector() )。除此之外,还要再声明一下模板参数。(template <class T>)

类模板的实例化

类模板实例化与函数模板实例化不同,类模板实例化需要在类模板名字后跟 <>,然后将实例化的类型放在 <> 中即可,类模板不是真正的类,而实例化的结果才是真正的类。

 // Vector类名,Vector<int>才是类型Vector<int> s1; //存储 int 类型数据的顺序表Vector<double> s2; //存储 double 类型数据的顺序表

http://www.hkcw.cn/article/EnmEOAtJoD.shtml

相关文章

第六十二节:深度学习-加载 TensorFlow/PyTorch/Caffe 模型

在计算机视觉领域,OpenCV的DNN(深度神经网络)模块正逐渐成为轻量级模型部署的利器。本文将深入探讨如何利用OpenCV加载和运行三大主流框架(TensorFlow、PyTorch、Caffe)训练的模型,并提供完整的代码实现和优化技巧。 一、OpenCV DNN模块的核心优势 OpenCV的DNN模块自3.3…

Linux系统下安装配置 Nginx

Windows Nginx https://nginx.org/en/download.htmlLinux Nginx https://nginx.org/download/nginx-1.24.0.tar.gz解压 tar -zxvf tar -zxvf nginx-1.18.0.tar.gz #解压安装依赖&#xff08;如未安装&#xff09; yum groupinstall "Development Tools" -y yum…

qwen3解读

1. 模型架构 重点&#xff1a; 思维模式和非思维模式这两种不同的操作模式集成到一个模型中。这样可以让用户在这些模式间切换&#xff0c;而不是在不同模型间切换。多阶段的后培训方法&#xff1a;增强推理和非推理模式。将基础模型和人的偏好结合。 预训练阶段&#xff1a…

用127.0.0.1访问VMware虚拟机中间件

文章目录 前言一、虚拟机安装、插件安装二、改虚拟机配置1.更改虚拟机使用的是 NAT 模式2.编辑 VMware 的 NAT 设置并添加端口转发 总结至此大功告成了&#xff01;&#xff01;&#xff01; 前言 docker 安装中间件很方便,平时使用windows作开发,如果想快速安装中间件,那么首…

【大模型部署】mac m1本地部署 ChatGLM3-6B 超详细教程

本人环境&#xff1a;macOS 15.5 (Sonoma) - Apple M1 / 16 G 目标&#xff1a;在 mac m1 16G 上 完全离线 的本地模型目录上&#xff0c;跑通官方 ChatGLM3-6B 目录 背景 & 踩坑记录 准备工作 新建 Conda 环境并安装依赖 关键环境变量 运行 composite_demo 常见报错与…

评标专家随机抽选系统-建设方案——仙盟创梦IDE

政策要求 抽选记录保存 专辑库管理 系统统计 抽选打印 系统分级管理 项目管理 系统分级管理 集团公司管理 专家补抽 评标专家随机抽选 1、系统分级管理合规 符合《数据安全法》第二十一条&#xff08;分类分级制度&#xff09;&#xff0c;安全按照不同职级&#xff0c;配置权…

2.5/Q2,Charls最新文章解读

文章题目&#xff1a;Trajectories of depressive symptoms and risk of chronic liver disease: evidence from CHARLS DOI&#xff1a;10.1186/s12876-025-03943-7 中文标题&#xff1a;抑郁症状的轨迹和慢性肝病风险&#xff1a;来自 CHARLS 的证据 发表杂志&#xff1a;BM…

win1011安装WinGet和Windows Terminal

前言 winget是微软推出的类似Ubuntu apt 的包管理器。安装winget建议一同安装微软推出的代替conhost.exe的新版命令提示符工具Windows Terminal。 安装 Windows Terminal 微软商店 github 安装后以管理员打开老版命令提示符&#xff0c;上方任务栏右键-默认值-终端-默认终端…

深 入 剖 析 单 链 表:从 原 理 到 实 战 应 用

深 入 剖 析 单 链 表&#xff1a;从 原 理 到 实 战 应 用 顺 序 表 的 问 题单 链 表单 链 表 与 顺 序 表 区 别相 关 概 念链 表 定 义单 链 表 定 义存 储 结 构 单 链 表 的 操 作 实 现代 码 全 貌 与 功 能 介 绍单 链 表 的 功 能 说 明代 码 效 果 展 示代 码 详 解S…

【LLM相关知识点】关于LLM项目实施流程的简单整理(一)

【LLM相关知识点】关于LLM项目实施流程的简单整理&#xff08;一&#xff09; 文章目录 【LLM相关知识点】关于LLM项目实施流程的简单整理&#xff08;一&#xff09;零、学习计划梳理&#xff1a;结合ChatGPT从零开始学习LLM & 多模态大模型一、大模型相关应用场景和头部企…

Vue 核心技术与实战day07

1. vuex概述 2. 构建 vuex [多组件数据共享] 环境 <template><div id"app"><h1>根组件- {{ title }}- {{ count }}</h1><input :value"count" input"handleInput" type"text"><Son1></Son1>…

【android bluetooth 案例分析 04】【Carplay 详解 3】【Carplay 连接之车机主动连手机】

1. 背景 在前面的文章中&#xff0c;我们已经介绍了 carplay 在车机中的角色划分&#xff0c; 并实际分析了 手机主动连接车机的案例。 感兴趣可以 查看如下文章介绍。 【android bluetooth 案例分析 04】【Carplay 详解 1】【CarPlay 在车机侧的蓝牙通信原理与角色划分详解】…

【stm32开发板】单片机最小系统原理图设计

一、批量添加网络标签 可以选择浮动工具中的N&#xff0c;单独为引脚添加网络标签。 当芯片引脚非常多的时候&#xff0c;选中芯片&#xff0c;右键选择扇出网络标签/非连接标识 按住ctrl键即可选中多个引脚 点击将引脚名称填入网络名 就完成了引脚标签的批量添加 二、电源引…

Linux --OS和PCB

目录 认识冯诺依曼系统 操作系统概念与定位 1.概念 2.设计OS的目的 3.OS的核心功能 4.系统调⽤和库函数概念 深⼊理解进程概念&#xff0c;了解PCB 1.基本概念与基本操作 2.描述进程-PCB 基本概念 task_ struct 的内容分类 认识冯诺依曼系统 在计算机中小到个人的笔…

2025最新版在Windows上安装Redis(仅限开发环境)

使用一位GitHub的博主做的Redis-Windows,截止现在更新到8.0.2 Releases redis-windows/redis-windows GitHub https://github.com/redis-windows/redis-windows/releases 我使用6.2.18版本做例子,使用6.2以上版本,因为一些语法,比如lpop,rpop,zrange,zdiff集合操作比旧版有…

[python]Prophet‘ object has no attribute ‘stan_backend‘解决方法

测试环境&#xff1a; prophet1.1.4 写代码&#xff1a; from prophet import Prophet modelProphet() print(123) 在anaconda prompt里面没有报错&#xff0c;但是打开jupyter notebook会报错Prophet object has no attribute stan_backend&#xff0c;据此猜测jupyter应该…

Python----目标检测(《基于区域提议网络的实时目标检测方法》和Faster R-CNN)

一、《基于区域提议网络的实时目标检测方法》 1.1、基本信息 标题&#xff1a;Faster R-CNN: Towards Real-Time Object Detection with Region Proposal Networks 作者&#xff1a;任少卿&#xff08;中国科学技术大学、微软研究院&#xff09;、何凯明&#xff08;微软研究…

流媒体基础解析:从压缩到传输的基本了解

流媒体&#xff0c;又称为流式媒体&#xff0c;已成为现代网络视频传输的核心技术。其基本原理是将连续的影像和声音信息经过精心设计的压缩&#xff08;编码&#xff09;处理后&#xff0c;妥善存放在网站服务器上。随后&#xff0c;这些压缩后的数据通过网络高效传输至终端用…

【MFC】如何设置让exe的控制台不会跟着exe退出而退出

在 Windows 下&#xff0c;MFC 程序&#xff08;如 echo.exe&#xff09;如果用 AllocConsole 创建了控制台窗口&#xff0c;默认情况下&#xff0c;当主程序&#xff08;exe&#xff09;退出时&#xff0c;控制台窗口也会自动关闭。这是操作系统的行为&#xff0c;不能直接阻止…

图像风格迁移笔记

图像风格迁移 最早实现风格迁移的原理:损失函数内容损失函数风格损失函数融合内容损失函数与风格损失函数可以融合多种风格图片的效果同一个网络可以生成多种风格图像的效果效果改进最早实现风格迁移的原理: 最早出现的论文的实现想法是将风格图像、内容图像、白噪声图像输入…