[C++] 模板template

目录

1、函数模板

1.1 函数模板概念

1.2 函数模板格式

1.3 函数模板的原理

1.4 函数模板的实例化

1.4.1 隐式实例化

1.4.2 显式实例化

1.5 模板参数的匹配原则

2、类模板

2.1 类模板的定义格式

2.2 类模板的实例化


讲模板之前呢,我们先来谈谈泛型编程:

泛型编程:编写与类型无关的通用代码,是代码复用的一种手段。模板是泛型编程的基础。
模板分为两类:函数模板与类模板

1、函数模板

1.1 函数模板概念

函数模板代表了一个函数家族,该函数模板与类型无关,在使用时被参数化,根据实参类型产生函数的特定类型版本。

1.2 函数模板格式

template<typename T1, typename T2,......,typename Tn>
返回值类型 函数名(参数列表){}

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

注意:typename是用来定义模板参数关键字,也可以使用class(切记:不能使用struct代替class) 。

1.3 函数模板的原理

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

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

1.4 函数模板的实例化

用不同类型的参数使用函数模板时,称为函数模板的实例化。模板参数实例化分为:隐式实例化和显式实例化。

1.4.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);return 0;
}

这里Add(a1, a2)与Add(d1, d2)都是隐式实例化,编译器会根据实参推出实际类型。

我们再来看一段代码:

template<class T>
T Add(const T& left, const T& right)
{return left + right;
}int main()
{int i = 1;double d = 1.1;Add(i, d);return 0;
}

该语句不能通过编译,因为在编译期间,当编译器看到该实例化时,需要推演其实参类型通过实参i将T推演为int,通过实参d将T推演为double类型,但模板参数列表中只有一个T,编译器无法确定此处到底该将T确定为int 或者 double类型而报错。

注意:在模板中,编译器一般不会进行类型转换操作,因为一旦转化出问题,编译器就需要背黑锅Add(i, d);

这里要解决这样的问题有两种方式:

1. 用户自己来强制转化;

2. 使用显式实例化。

int main()
{int i = 1;double d = 1.1;Add(i, (int)d);return 0;
}

1.4.2 显式实例化

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

template<class T>
T Add(const T& left, const T& right)
{return left + right;
}
int main()
{int i = 1;double d = 1.1;Add<int>(i, d);// 显式实例化为intAdd<double>(i, d);// 显示实例化为doublereturn 0;
}

如果类型不匹配,编译器会尝试进行隐式类型转换,如果无法转换成功编译器将会报错。

1.5 模板参数的匹配原则

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

// 专门处理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); // 模板函数可以生成更加匹配的版本,编译器根据实参生成更加匹配的Add函数 
}

3. 模板函数不允许自动类型转换,但普通函数可以进行自动类型转换

2、类模板

2.1 类模板的定义格式

template<class T1, class T2, ..., class Tn>
class 类模板名
{// 类内成员定义
};
template<class T>
class stack
{
public:stack();//声明,在类外面定义~stack(){delete[] _a;_top = _capacity = 0;}
private:T* _a;int _top;int _capacity;
};// 注意:类模板中函数放在类外进行定义时,需要加模板参数列表
template<class T>
stack<T>::stack(): _a(nullptr), _top(0), _capacity(0)
{}

2.2 类模板的实例化

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

int main()
{stack<int> st1;stack<char> st2;return 0;
}

如果我们的栈是要存储int类型的数据,我们就实例化为int,如果是存储char类型的数据,就实例化为char类型。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/39500.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Qt读写Excel--QXlsx编译为静态库2

1、概述&#x1f954; 在使用QXlsx时由于源码文件比较多&#xff0c;如果直接加载进项目里面&#xff0c;会增加每次编译的时间&#xff1b; 直接将源码加载进项目工程中&#xff0c;会导致项目文件非常多&#xff0c;结构变得更加臃肿&#xff1b; 所以在本文中将会将QXlsx编译…

骨传导耳机头晕是怎么回事?骨传导耳机好不好

骨传导耳机在音频传输上采用了不同于传统耳机的方式。它们通过将声音振动传递到颞骨&#xff0c;然后通过骨骼传导到内耳&#xff0c;从而使用户能够听到音乐或声音。 然而&#xff0c;有些人在使用骨传导耳机时可能会感到头晕。这可能与以下几个原因有关&#xff1a; 1、刚开…

prometheusalert区分告警到不同钉钉群

方法一 修改告警规则 - alert: cpu使用率大于88%expr: instance:node_cpu_utilization:ratio * 100 > 88for: 5mlabels:severity: criticallevel: 3kind: CpuUsageannotations:summary: "cpu使用率大于85%"description: "主机 {{ $labels.hostname }} 的cp…

99%的Python用户都不知道的f-string隐秘技巧

f-string想必很多Python用户都基础性的使用过&#xff0c;作为Python3.6版本开始引入的特性&#xff0c;通过它我们可以更加方便地向字符串中嵌入自定义内容&#xff0c;但f-string真正蕴含的功能远比大多数用户知道的要丰富&#xff0c;今天我们就来一起get它们~ 「最基础用法…

ajax解析

Ajax&#xff08;Asynchronous JavaScript and XML&#xff09;是一种用于在不重新加载整个页面的情况下与服务器交换数据的技术。它通过异步的方式发送请求和接收响应&#xff0c;能够实现在后台与服务器进行数据交互&#xff0c;然后更新页面的部分内容&#xff0c;从而提升用…

【CI/CD】基于 Jenkins+Docker+Git 的简单 CI 流程实践(上)

基于 JenkinsDockerGit 的简单 CI 流程实践&#xff08;上&#xff09; 在如今的互联网时代&#xff0c;随着软件开发复杂度的不断提高&#xff0c;软件开发和发布管理也越来越重要。目前已经形成一套标准的流程&#xff0c;最重要的组成部分就是 持续集成 及 持续交付、部署。…

GPU编程基础-CUDA实现图像处理

GPU编程基础-CUDA实现图像处理 1. 相关基础概念1.1 Host和Device程序1.2 Kernel程序1.3 SIMT和SIMD1.4 GPU计算的 Occupancy指标1.5 GPU计算的基本流程2. GPU计算框架与过程说明3. 一个基于CUDA的图像处理例子4. 一些报错解决1. 相关基础概念 1.1 Host和Device程序 在CPU上运行…

Effective C++学习笔记(7)

目录 条款41&#xff1a;了解隐式接口和编译多态条款42&#xff1a;了解typename的双重意义条款43&#xff1a;学习处理模板化基类内的名称条款44&#xff1a;将与参数无关的代码抽离templates条款45&#xff1a;运用成员函数模板接受所有兼容类型条款46&#xff1a;需要类型转…

opencv,opengl,osg,vulkan,webgL,opencL,cuda,osg,vtk,ogre的区别

OpenCV OpenCV是一个基于BSD许可&#xff08;开源&#xff09;发行的跨平台计算机视觉和机器学习软件库&#xff0c;可以运行在Linux、Windows、Android和Mac OS操作系统上。 它轻量级而且高效——由一系列 C 函数和少量 C 类构成&#xff0c;同时提供了Python、Ruby、MATLAB等…

avue多选列表根据后端返回的某个值去判断是否选中;avue-curd多选回显

效果如上&#xff1a; getSiteList().then(res > {//列表数据this.siteData res.data.datathis.$nextTick(()>{this.siteData.forEach(item>{//业务条件if(item.configid&&item.configid!0&&item.configid>0){//符合条件时调用选中的方法this.$…

JAVASE---数组的定义与使用

数组的基本概念 什么是数组 数组是具有相同类型元素的集合&#xff0c;在内存中连续存储。 1. 数组中存放的元素其类型相同 2. 数组的空间是连在一起的 3. 每个空间有自己的编号&#xff0c;起始位置的编号为0&#xff0c;即数组的下标 数组的创建及初始化 数组的创建 T[…

mybatis高级特性

文章目录 数据库事务管理批处理插件扩展持久化和ORM缓存机制 数据库事务管理 通过注解方式&#xff1a; 在需要进行事务管理的方法上添加Transactional注解&#xff0c;该注解可以用于类或方法上。在配置文件中开启事务管理器&#xff0c;并指定事务管理器的类型和连接池等相关…

Java SpringBoot Vue智能停车系统

基础环境 JDK1.8、Maven、Mysql、IntelliJ IDEA 内置功能 系统管理&#xff1a;角色管理、接口管理、系统菜单、全局配置 账号管理&#xff1a;用户管理、合作单位 系统监控&#xff1a;监控大屏、日志监控 财务管理&#xff1a;订单列表 停车记录&#xff1a;停车记录 车辆管…

Labview选项卡之实现被选择选项卡工作

文章目录 前言一、使用选项卡二、实现被选择选项卡工作1、需求2、分析3、实现①、前面板②、程序框图 三、效果展示四、源码自取 前言 有些时候&#xff0c;我们做界面&#xff0c;需要好多个界面切换。如果是同一个 VI 里界面切换&#xff0c;一般都是选项卡了。切换不同选项…

使用phpstorm开发调试thinkphp

1.环境准备 1.开发工具下载&#xff1a;PhpStorm: PHP IDE and Code Editor from JetBrains 2.PHP下载&#xff1a;PHP: Downloads 3. PHP扩展&#xff1a;PECL :: Package search 4.用与调试的xdebug模块&#xff1a; Xdebug: Downloads xdebug模块&#xff0c;如果是php8以…

23.8.16日总结

原先写的评论是每级评论用缩进来区分&#xff0c;所以最多设置的是九级评论&#xff0c;修改了排版和格式&#xff1a; 还有管理员页面&#xff0c;查看文章时可以进行点赞&#xff0c;收藏的操作&#xff0c;现在进行了修改&#xff0c;将相关操作隐藏。 还有点击查看未发布…

js如何获取字符串大小是几M

js如何获取字符串大小是几M 在JavaScript中&#xff0c;可以使用以下方法来获取字符串的大小&#xff08;以字节为单位&#xff09;&#xff1a; function getStringSizeInBytes(str) {// 使用UTF-8编码计算字符串的字节长度let totalBytes new Blob([str]).size;// 将字节长…

14-矩阵相乘及其运算法则

矩阵与向量的乘法 在这一篇文章中我们就将基于上一篇重新审视矩阵的这个视点来理解矩阵的乘法&#xff0c;那么在这一篇&#xff0c;我们主要来看一下矩阵和向量的乘法。这里这个线性方程组是上一小节给大家举的模拟的一个非常简单的小型经济系统的例子&#xff0c;我们可以把…

文件的导入与导出

文章目录 一、需求二、分析1. Excel 表格数据导出2. Excel 表格数据导入一、需求 在我们日常开发中,会有文件的导入导出的需求,如何在 vue 项目中写导入导出功能呢 二、分析 以 Excel 表格数据导出为例 1. Excel 表格数据导出 调用接口将返回的数据进行 Blob 转换,附: 接…

logstash日志换行处理小解

logstash主用于日志实时数据收集、解析&#xff0c;并将数据转发的工具&#xff0c;内置的功能也相当强大。但&#xff0c;同时意味着&#xff0c;他可能接收到各种情况的数据。 此处&#xff0c;我们主要讲解我实际使用中&#xff0c;碰到的一个小问题&#xff0c;换行(\n)。…