【C++】初识模板:函数模板和类模板

目录

一、模板函数

1、函数模板的概念

2、函数模板的格式

3、函数模板的原理

4、函数模板实例化

5、 模板参数的匹配原则

二、类模板 

1 、类模板的定义格式

2 、类模板的实例化

3、模板类示例


一、模板函数

1、函数模板的概念

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

2、函数模板的格式

模板函数通过在函数定义前使用关键字 “template” 和一个或多个模板参数来定义。模板参数可以是类型参数或非类型参数。类型参数是用于指定函数参数类型的通用标识符,非类型参数则是用于指定常量值或常量表达式。

下面是一个简单的模板函数示例:

template <class T>
T findMax(T a, T b) {return (a > b) ? a : b;
}

在上面的示例中,我们定义了一个名为 “findMax” 的模板函数。该函数接受两个类型相同的参数,并返回较大的那个参数。通过使用模板参数 “T”,我们可以在不同的上下文中使用相同的函数实现。

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

3、函数模板的原理

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

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

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

 

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

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<int>(a1, d1);return 0;
}
【注意】:如果类型不匹配,编译器会尝试进行隐式类型转换,如果无法转换成功编译器将会报错。

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】、模板函数不允许自动类型转换,但普通函数可以进行自动类型转换


二、类模板 

1 、类模板的定义格式

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

2 、类模板的实例化

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

3、模板类示例

模板类的定义类似于模板函数,需要使用关键字 “template” 和一个或多个模板参数来定义。模板参数可以是类型参数或非类型参数。类型参数用于指定类中的数据类型,非类型参数用于指定常量值或常量表达式。

下面是一个简单的模板类示例:

template <class T>
class Stack {
private:T* data;int top;int capacity;public:Stack(int maxCapacity) {capacity = maxCapacity;data = new T[capacity];top = -1;}~Stack() {delete[] data;}void push(T element) {if (top == capacity - 1) {throw std::overflow_error("Stack is full");}data[++top] = element;}T pop() {if (top == -1) {throw std::underflow_error("Stack is empty");}return data[top--];}bool isEmpty() {return (top == -1);}int size() {return top + 1;}
};

在上面的示例中,我们定义了一个名为 “Stack” 的模板类。它是一个栈数据结构的实现,可以用于存储各种类型的数据。通过使用模板参数 “T”,我们可以在不同的上下文中使用相同的类定义来创建具有不同数据类型的栈对象。

使用模板类时,我们需要在创建对象时指定具体的模板参数类型。例如:

int main() {Stack<int> intStack(10);Stack<double> doubleStack(20);intStack.push(5);doubleStack.push(3.14);intStack.pop();doubleStack.pop();return 0;
}

在上面的示例中,我们分别使用了整数和浮点数作为模板参数类型来创建了两个栈对象。通过这种方式,我们可以在不同的上下文中使用相同的类实现,提高代码的复用性和灵活性。

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

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

相关文章

C语言之预处理详解

目录 1. 预定义符号2. #define定义常量3. #define定义宏练习 4. 带有副作用的宏参数5. 宏替换的规则6. 宏函数的对比宏和函数的一个对比 7. #和###运算符##运算符 8. 命名约定9. #undef10. 命令行定义11. 条件编译常见的条件编译 12. 头文件的包含头文件的包含方式库文件包含嵌…

通过遵循最佳做法来提高 EDA 和 HPC 应用程序的 Azure NetApp 文件性能

介绍 Azure NetApp 文件是一项托管存储解决方案&#xff0c;适用于各种方案&#xff0c;包括高性能计算 (HPC) 基础结构。 低延迟和每秒高 I/O 操作数 (IOPS) 对于大规模企业而言是一种很好的组合。 假设你就职于一家半导体公司。 你的任务是设计公司的集成电路芯片&#xff…

新春快乐(烟花、春联)【附源码】

新春快乐 一&#xff1a; C语言 -- 烟花二&#xff1a;Python -- 春联三&#xff1a;Python -- 烟花四&#xff1a;HTML -- 烟花 一&#xff1a; C语言 – 烟花 运行效果&#xff1a; #include <graphics.h> #include <math.h> #include <time.h> #include…

电商小程序07显示用户个人信息

目录 1 全局变量2 控制登录按钮显示3 设置布局4 搭建我的页面5 修改个人信息总结 在登录章节我们已经实现了用户名和密码登录首页的功能&#xff0c;在登录之后&#xff0c;可以切换到我的页面&#xff0c;显示用户的头像和名称&#xff0c;可以修改个人信息。本篇我们介绍一下…

【Spring MVC篇】参数的传递及json数据传参

个人主页&#xff1a;兜里有颗棉花糖 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 兜里有颗棉花糖 原创 收录于专栏【Spring MVC】 本专栏旨在分享学习Spring MVC的一点学习心得&#xff0c;欢迎大家在评论区交流讨论&#x1f48c; 目录 一、普通参数的传…

STM32能够做到数据采集和发送同时进行吗?

STM32能够做到数据采集和发送同时进行吗&#xff1f; 在开始前我有一些资料&#xff0c;是我根据网友给的问题精心整理了一份「STM32的资料从专业入门到高级教程」&#xff0c; 点个关注在评论区回复“888”之后私信回复“888”&#xff0c;全部无偿共享给大家&#xff01;&am…

专业140+总分420+河海大学863信号与系统考研经验电子信息通信与信息技术,真题,大纲,参考书。

今年的成绩出来倍感欣慰&#xff0c;决定考研的时候并没有想到自己可以考出420的分数&#xff0c;通过自己一年来的努力&#xff0c;成功上岸&#xff0c;期中专业课863信号与系统140接近满分&#xff08;非常感谢信息通信Jenny老师的专业课辅导和平时悉心答疑&#xff0c;不厌…

【MATLAB源码-第138期】基于matlab的D2D蜂窝通信仿真,对比启发式算法,最优化算法和随机算法的性能。

操作环境&#xff1a; MATLAB 2022a 1、算法描述 D2D蜂窝通信介绍 D2D蜂窝通信允许在同一蜂窝网络覆盖区域内的终端设备直接相互通信&#xff0c;而无需数据经过基站或网络核心部分转发。这种通信模式具有几个显著优点&#xff1a;首先&#xff0c;它可以显著降低通信延迟&…

波奇学Linux: 文件描述符

文件和操作系统的关系 操作系统控制进程&#xff0c;文件的打开是在进程中进行。意味着用来控制进程的PCB必然有文件的信息&#xff0c;操作系统通过控制PCB的信息来控制文件的读写。 Q1&#xff1a;如何证明文件打开是在进程中进行&#xff1f; 编写c文件调用fopen来操作文件…

SpringBoot 接入讯飞星火大模型实现对话

申请地址 https://xinghuo.xfyun.cn/sparkapi?scrprice 免费申请200万Token 开发文档 https://www.xfyun.cn/doc/spark/Web.html#_1-接口说明 页面最下面有相关demo可以参考 介绍 接口是以套接字的形式分段返回&#xff0c;而且非http请求&#xff0c;比较繁琐&#xff0c;官…

如何使用Airtest进行UI自动化测试

一、环境搭建 1、Airtest客户端下载 访问官网http://airtest.netease.com/&#xff0c;根据自己的系统下载相应的客户端安装&#xff1b; 2、python工具下载与环境搭建 在本地python环境中安装airtest和pocoui&#xff0c;然后用命令行运行脚本&#xff1b; 1、建议使用3.…

猫头虎分享已解决Bug || RuntimeError: size mismatch, m1: [32 x 100], m2: [500 x 10]

博主猫头虎的技术世界 &#x1f31f; 欢迎来到猫头虎的博客 — 探索技术的无限可能&#xff01; 专栏链接&#xff1a; &#x1f517; 精选专栏&#xff1a; 《面试题大全》 — 面试准备的宝典&#xff01;《IDEA开发秘籍》 — 提升你的IDEA技能&#xff01;《100天精通鸿蒙》 …

奶茶点餐|奶茶店自助点餐系统|基于微信小程序的饮品点单系统的设计与实现(源码+数据库+文档)

奶茶店自助点餐系统目录 目录 基于微信小程序的饮品点单系统的设计与实现 一、前言 二、系统功能设计 三、系统实现 1、商品信息管理 2、商品评价管理 3、商品订单管理 4、用户管理 四、数据库设计 1、实体ER图 2、具体的表设计如下所示&#xff1a; 五、核心代码 …

Linux操作系统基础(八):Linux的vi/vim编辑器

文章目录 Linux的vi/vim编辑器 一、vi/vim编辑器介绍 二、打开文件 三、VIM编辑器的三种模式(重点) 四、命令模式相关命令 五、底行模式相关命令 Linux的vi/vim编辑器 一、vi/vim编辑器介绍 vi是visual interface的简称, 是Linux中最经典的文本编辑器 vi的核心设计思想…

在 Windows上恢复删除照片的 4 种有效方法

您是否曾在 Windows 7/8/10/11 中不小心删除过照片&#xff1f;如何轻松快速地恢复已删除的照片&#xff1f;在这里这篇文章列出了几种在Windows 11/10/8/7中恢复已删除照片的可行方法&#xff0c;而MiniTool数据恢复软件 是丢失照片恢复的最佳选择。 意外删除的照片 根据一项…

蓝桥杯官网练习题(翻转)

问题描述 小蓝用黑白棋的 n 个棋子排成了一行&#xff0c;他在脑海里想象出了一个长度为 n 的 01 串 T&#xff0c;他发现如果把黑棋当做 1&#xff0c;白棋当做 0&#xff0c;这一行棋子也是一个长度为 n 的 01 串 S。 小蓝决定&#xff0c;如果在 S 中发现一个棋子…

口腔助手|口腔挂号预约小程序|基于微信小程序的口腔门诊预约系统的设计与实现(源码+数据库+文档)

口腔小程序目录 目录 基于微信小程序的口腔门诊预约系统的设计与实现 一、前言 二、系统功能设计 三、系统实现 1、小程序前台界面实现 2、后台管理员模块实现 四、数据库设计 1、实体ER图 2、具体的表设计如下所示&#xff1a; 五、核心代码 六、论文参考 七、最新…

【调试】pstore原理和使用方法总结

什么是pstore pstore最初是用于系统发生oops或panic时&#xff0c;自动保存内核log buffer中的日志。不过在当前内核版本中&#xff0c;其已经支持了更多的功能&#xff0c;如保存console日志、ftrace消息和用户空间日志。同时&#xff0c;它还支持将这些消息保存在不同的存储…

JavaScript 遍历文档生成目录结构

JavaScript 遍历文档生成目录结构 要遍历 HTML 文档并生成目录结构&#xff0c;你可以使用 JavaScript 来进行 DOM 操作和遍历。以下是一个简单的示例代码&#xff0c;演示了如何遍历文档中的标题元素&#xff08;例如 <h1>、<h2>、<h3> 等&#xff09;&…

Rust基础拾遗--核心功能

Rust基础拾遗 前言1.所有权与移动1.1 所有权 2.引用3.特型与泛型简介3.1 使用特型3.2 特型对象3.3 泛型函数与类型参数 4.实用工具特型5.闭包 前言 通过Rust程序设计-第二版笔记的形式对Rust相关重点知识进行汇总&#xff0c;读者通读此系列文章就可以轻松的把该语言基础捡起来…