C++里面的“百变怪”:模板

news2024/9/20 17:52:40

🌞0.前言

言C++之言,聊C++之识,以C++会友,共向远方。各位博友的各位你们好啊,这里是持续分享C++知识的小赵同学,今天要分享的C++知识是模板 ,在这一章,小赵将会向大家聊聊C++的模板知识 。✊

 相信大家对于精灵宝可梦里面的百变怪是相当的熟悉,它可以变成各种各样的精灵宝可梦。而我们今天要介绍的C++里面的一个主人公也是一个百变怪,它可以变成各种各样的类型,好了话不多说快速开始进入我们今天的知识闲聊。

🚈1. 泛型编程

引入:还记得我们上次是怎么解决两个变量之间的求和的吗?我们前面的博客说我们写求和函数只能针对某一种类型进行求和,可是如果是其他类型就没办法解决,于是我们引入了函数重载。可是引入函数重载真的可以解决我们的问题吗?

int Sum(int a,int b)
{
	return a + b;
}
double Sum(double a, double b)
{
	return a + b;
}
long long int Sum(long long int a, long long int b)
{
	return a + b;
}
.......

我们发现有的时候我们要处理的求和类型太多,我们根本没办法将他们一个一个初始化。(这里的例子其实不太好,比较函数和交换函数好,这里主要还是为了和前面文章有个连接)

而且我们发现这样个一个写函数重载真的很累人,而且如果我这个时候用这个求和函数,还得去看我写的求和函数重载里面有木有我要的,没有我还要自己加,所以基于以上的种种问题和原因,

我们开始思考如何去让我们的代码简化。

我们是否可以引入一种东西像百变怪一样按照我们的需求自由变化类型。

 又或是也能够存在这样一个模具,通过给这个模具中填充不同材料(类型),来获得不同材料的铸件

(即生成具体类型的代码)。

由此我们的前人引入了泛型编程,让我们的代码更加简短,同时可以满足我们的不同需求。 

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

而其中最典型的就是我们的模板: 

 🚈2. 函数模板

🚝2.1 函数模板概念

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

🚝 2.2 函数模板格式

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

返回值类型 函数名(参数列表){}

下面直接实际用下解决我们上面的问题:

template<typename T>
T Sum( T left, T right)
{
   return left+right;
}

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

🚝 2.3 函数模板的原理

 那么如何解决上面的问题呢?大家都知道,瓦特改良蒸汽机,人类开始了工业革命,解放了生产力。机器生 产淘汰掉了很多手工产品。本质是什么,重复的工作交给了机器去完成。有人给出了论调:懒人创造世界。

 

函数模板是一个蓝图,它本身并不是函数,是编译器用使用方式产生特定具体类型函数的模具。所以其实模板就是将本来应该我们做的重复的事情交给了编译器。(就像我们前面的for(auto ch:num)又或是auto都是把我们的事情交给了编译器。)

这里附上小赵一贯的代码解析图

( 真的很像百变怪(或者前面的模具),要它变什么就变什么。)

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

🚝 2.4 函数模板的实例化

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

✈️2.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(a, (int)d);//强制类型转化
   return 0;
}

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

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

我一个学C++的老朋友说这里的隐式类型转化就像是一个人指着东西告诉你,它要什么,而显示类型转化就是直接告诉你。感觉还是蛮形象的。(我另一个朋友说这就像女朋友,隐式类型就是让你猜她想要什么,显示就是直接告诉你。我感觉怪怪的)(我看不如百变怪,显示就是你告诉它变什么,隐式就是你指着一个精灵告诉它变什么。)

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

🚝2.5 模板参数的匹配原则

 ✈️2.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版本
}

这里为什么int类型的用的非模板类型呢?因为编译器也懒。就好像是我们家里有一个刚好的能穿的又好看的衣服,还会跑去街上无缘无故多买一个吗?而且编译器人家实例化一个模板也是很累的人也不想动,所以有现成的还是先用现成的没有再去买。

✈️2.5.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函
数
}

 这里很明显,现成的并不完全匹配当下的情况,而模板实例化出来的更加好(这里可以看出计算机的严谨性,不能偷的懒坚决不偷)。

✈️2.5.3模板函数不允许自动类型转换,但普通函数可以进行自动类型转换(隐式类型转换)。

 需要注意的是,我们刚才说如果有模板且我们的现成的不满足时候会使用模板去实例化一个,但如果我们实在没有呢?这就有两种情况,一种可隐式类型转化,一种不可以。

int Sum(int a, int b)
{
	return a + b;
}
int main()
{
	cout<<Sum(2, 2.3);//可以隐式类型转换
    cout<<Sum(2, 'a');//可以隐式类型转换//这里'a'转化成ascll码
    //Sum(2, a);//报错//这里的a被识别为变量,字符要加'',属于常见错误
	cout << Sum(2, "ssdd");//报错
}

 这里的隐式类型转化和我们前面说的差不多就是会先生成一个临时变量,在赋值给前面的。(但是必须要类接近才可以,不接近不可以。)

大致就是这样一个过程 

 🚈3. 类模板

 有了上述的知识再理解类模板就不难了。

🚝3.1 类模板的定义格式 

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;
}

 这里不需要全看懂,后面我们手撕解剖这里的vector代码,大家只需要大概知道怎么去写类模板就行。

🚝3.2 类模板的实例化 

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

// Vector类名,Vector才是类型
Vectorint> s1; Vectordouble> s2;

也是一样看懂怎么实例化就行。  

💎4.结束语

其实模板的知识还没有全部聊完,因为后面的模板的一些东西其实也是为了解决大家在模板使用中出现的问题,而且主要偏向于类,所以我们会在手撕完STL后和大家继续聊模板剩下的知识。 

好了小赵今天的分享就到这里了,如果大家有什么不明白的地方可以在小赵的下方留言哦,同时如果小赵的博客中有什么地方不对也希望得到大家的指点,谢谢各位家人们的支持。你们的支持是小赵创作的动力,加油。

如果觉得文章对你有帮助的话,还请点赞,关注,收藏支持小赵,如有不足还请指点,方便小赵及时改正,感谢大家支持!!!

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

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

相关文章

实时音视频之医疗手术示教技术方案探究

背景与重要性 医疗手术示教是现代医学教育中不可或缺的一环&#xff0c;它通过将手术室内医生的手术过程以及手术室内的各种医疗设备的视频资料真实呈现给实习医生或观摩人员&#xff0c;以达到教学或学术交流的目的。随着医疗技术的不断进步和医学教育的深入发展&#xff0c;…

各类软件在Linux上的安装

mysql安装 5.7版本 mysql的程序在centos官方的库中是没有的&#xff0c;需要切换到淘宝的镜像&#xff0c;这个前面有教程或者配置mysql的源 yum -y install rpm rpm --import https://repo.mysql.Com/RPM-GPG-KEY-mysqL-2022 rpm -Uvh http://repo.mysql.com//mysql57-commun…

自定义EPICS在LabVIEW中的测试

继续上一篇&#xff1a;LabVIEW中EPICS客户端/服务端的测试 变量定义 You can use CaLabSoftIOC.vi to create new EPICS variables and start them. CA Lab - LabVIEW (Realtime) EPICS INPUT: PV set Cluster-array of names, data types and field definitions to crea…

web前端-HTML常用标签(三)

一、表格标签 表格是实际开发中非常常用的标签: 1.表格的主要作用&#xff1a; 表格主要用于显示、展示数据&#xff0c;因为它可以让数据显示的非常的规整&#xff0c;可读性非常好。特别是后台展示数据的时候&#xff0c;能够熟练运用表格就显得很重要。一个清爽简约的表格…

多少岁转行网络安全不算晚?零基础想跳槽(转行)网络安全,看这篇就够了

&#x1f91f; 基于入门网络安全/黑客打造的&#xff1a;&#x1f449;黑客&网络安全入门&进阶学习资源包 奉劝所有零基础想入门&#xff08;转行&#xff09;网络安全的朋友&#xff0c;麻烦转行前&#xff0c;一定要对网络安全行业做一个大概了解&#xff0c;不要一点…

WriteUp - hackthebox-Labyrinth Linguist

题目靶场地址&#xff1a;https://ctf.hackthebox.com/ 先启动环境再下载项目文件&#xff1a; 项目文件压缩包解压密码&#xff1a;hackthebox 访问项目环境页面&#xff0c;是一个简单的web&#xff0c;输入什么就输出什么&#xff0c;直接看项目文件&#xff0c;是一个ja…

八叉树,分裂空间的魔法师【Unity】

八叉树,分裂空间的魔法师 前往我的博客阅读,享受免费无广告的体验 诞生 当我们要做物理碰撞检测的时候,例如一枚子弹射了出去,我们或许会选择遍历所有的物体,通过运算判断是否相交,是否发生碰撞,但这不理想,尤其是面对成千上万物体的时候,计算量极其恐怖。 同样的,…

在近一年内获得过新融资的中国独角兽企业

独角兽公司的概念源于 2013 年美国著名的 Cowboy venture 的投资人 Aileen Lee她将“成立时间较短、由投资人或者估值机构估值超过10 亿美元的未上市公司”定义为独角兽公司。独角兽也就是那些创业公司中的佼佼者。21 世纪至今&#xff0c;人类多个领域取得了显著的技术进步和突…

FreeRTOS(速记版)

第一章 初识 FreeRTOS 1.1 FreeRTOS简介 FreeRTOS 采用了 MIT 开源许可&#xff0c;这允许将 FreeRTOS 操作系统用于商业应用&#xff0c;并且不需要公开源代码。此外&#xff0c;FreeRTOS 还衍生出了另外两个操作系统&#xff1a;OpenRTOS 和 SafeRTOS&#xff0c;其中 OpenR…

探究文本完全对齐技术:从理论到代码

文本完全对齐算法解析与实现 引言 在编辑文档、设计书籍版面或网页时&#xff0c;通常需要将文本进行格式化对齐&#xff0c;以提升视觉吸引力和易读性。 一种广泛采用的对齐技术是所谓的“完全对齐”&#xff0c;这意味着文本的每一行的起始和结束位置都要对齐整齐。 虽然许多…

暴雨液冷服务器硬刚液冷放量元年

AI&#xff08;人工智能&#xff09;不断向前&#xff0c;作为AI三驾马车之一&#xff0c;算力需求始终如影随形。 近日&#xff0c;财经记者走访了河南郑州多家服务器厂商、大模型公司和算力中心。在走访中&#xff0c;记者发现&#xff0c;液冷技术正被算力行业青睐&#xf…

3GPP How to manage a project?

有人问:"3GPP 每个release都做了哪些方面的增强&#xff1f;应该有专门的文档介绍吧?"那肯定是有的&#xff0c;其实按照 https://t.zsxq.com/zbSox 中的方法就能找到那个文档。这篇我们整体浏览看下3GPP是如何handle project&#xff0c;这其中就会具体涉及哪些内…

ctfshow-web入门-sql注入(web244-web247)error 报错注入

目录 1、web244 2、web245 3、web246 4、web247 1、web244 在它查询框这里随便输什么都没有回显 还是在 api 接口下传参&#xff0c;输入存在 id&#xff1a; /api/?id1 查询成功 输入不存在的 id&#xff1a; /api/?id0 查询失败 追加单引号后&#xff0c;报 sql 语法…

从零到一,数字文创IP是如何在基地中孵化成长的?

在数字时代的浪潮下&#xff0c;数字文创IP孵化基地正成为培育创新的肥沃土壤&#xff0c;见证着一个个数字文创 IP 从无到有、茁壮成长。 数字文创IP孵化基地首先为创意的萌发提供了空间。这里汇聚了各路富有创造力的人才&#xff0c;他们的思想在这里碰撞&#xff0c;灵感的火…

网络原理(3)—— 应用层、传输层(TCP)

1. 应用层 日常开发中最常用到的一层&#xff0c;主要涉及到两种情况&#xff1a; 1) 使用现成的应用层协议 2) 自己定义应用层协议 1.1 自定义应用层协议的流程 1. 明确前后端交互过程中需要传递哪些信息 实例&#xff1a;开发一个外卖软件 打开软件&#xff0c;首先需要展…

Win11安装mysql5.7.24

Win11安装mysql5.7.24 资源文件mysql安装过程 资源文件 mysql5.7.24免安装压缩包 下载链接&#xff1a; https://download.csdn.net/download/weixin_44174685/89738053 DirectX&#xff08;用来修复缺失dll&#xff09; 下载链接&#xff1a;https://download.csdn.net/downl…

App弱网测试是怎么测试的

一、网络测试的一般流程 step1&#xff1a;首先要考虑网络正常的情况 ① 各个模块的功能正常可用 ② 页面元素/数据显示正常 step2&#xff1a;其次要考虑无网络的情况 ① APP各个功能在无网络情况下是否可用 ② APP各个页面之间切换是否正常 ③ 发送网络请求时是否…

永成防回水防回气装置脚踏实地老厂家

永成防回水防回气装置脚踏实地老厂家&#xff0c;分歧式防爆器是安装在瓦斯抽放管路中的简易防爆装置。 来吧&#xff0c;有业务就冲着我来。 别让我的同行太辛苦&#xff0c; 我在这里&#xff0c;等你来。 本防回水防回气装置是一种用于煤矿瓦斯管路爆渣和燃烧时防止回火、防…

为什么说开放式耳机值得买?打工人通勤必备的蓝牙耳机推荐

开放式耳机值得购买&#xff0c;主要有以下几方面原因&#xff1a; 佩戴舒适性高&#xff1a; 不压迫耳道&#xff1a;开放式耳机不进入耳道&#xff0c;不会对耳道产生压迫&#xff0c;避免了入耳式耳机长时间佩戴可能导致的耳道疼痛、肿胀等不适状况。无论是小耳道用户&…

91、K8s之ingress上集

一、Ingress service模式&#xff1a; loadbalance NodePort&#xff1a;每个节点都会有一个指定的端口 30000-32767 内网 clusterip&#xff1a;默认模式&#xff0c;只能pod内部访问 externalName&#xff1a;需要dns提供域名 1.1、对外提供服务的ingress service&…