C++第十四弹---模板初阶

 ✨个人主页: 熬夜学编程的小林

💗系列专栏: 【C语言详解】 【数据结构详解】【C++详解】

目录

1、泛型编程

 2、函数模板

2.1、函数模板的概念

2.2、函数模板的格式

2.3、函数模板的原理

2.4、函数模板的实例化

2.5、模板参数的匹配原则

3、类模板

3.1、类模板的定义格式

3.2、类模板的实例化

总结


1、泛型编程

什么是泛型编程呢?

在计算机程序设计领域,为了避免因数据类型的不同,而被迫重复编写大量相同业务逻辑的代码,人们发展的泛型及泛型编程技术。所以泛型,实质上就是不使用具体数据类型(例如 int、double、float 等),而是使用一种通用类型来进行程序设计的方法,该方法可以大规模的减少程序代码的编写量,让程序员可以集中精力用于业务逻辑的实现。

如何实现一个通用的交换函数呢?

如果按照我们C语言函数的实现,需要创建多个函数名不同的函数,但是我们学习了C++可以通过重载函数进行实现,创建多个函数,函数名相同,但是参数不同。

C++重载函数实现如下:

void Swap(int& left, int& right)
{
int temp = left;
left = right;
right = temp;
}
void Swap(double& left, double& right)
{
double temp = left;
left = right;
right = temp;
}
void Swap(char& left, char& right)
{
char temp = left;
left = right;
right = temp;
}
......

通过上面的代码我们可以发现使用函数重载虽然可以实现,但是有一下几个不好的地方

1. 重载的函数仅仅是类型不同,代码复用率比较低,只要有新类型出现时,就需要用户自己增加对应的函数。
2. 代码的可维护性比较低,一个出错可能所有的重载均出错。


那我们能否告诉编译器一个模子,让编译器根据不同的类型利用该模子来生成代码呢?


如果在C++中,也能够存在这样一个模具,通过给这个模具中填充不同材料(类型),来获得不同材料的铸件(即生成具体类型的代码),那将会节省许多头发。巧的是前人早已将树栽好,我们只需在此乘凉。

此处就可以用到我们C++的模板,也是泛型编程的基础。(模板包括函数模板和类模板)

 2、函数模板


2.1、函数模板的概念


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


2.2、函数模板的格式

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

//template、typename均为关键字,T为template的首字母大写,此处可以根据自己喜好选择字母,通常使用T+数字

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

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


2.3、函数模板的原理


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

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

在编译器编译阶段,对于模板函数的使用,编译器需要根据传入的实参类型来推演生成对应类型的函数以供调用。

比如:当用double类型使用函数模板时,编译器通过对实参类型的推演,将T确定为double类型,然后产生一份专门处理double类型的代码,对于字符类型也是如此。


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

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

template<class T>
T Add(const T& left, const T& right)
{return left + right;
}
int main(void)
{int a = 10;double b = 20.0;// 显式实例化  尖括号内部确定模板的类型Add<int>(a, b);return 0;
}

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


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);      // 与非模板函数匹配,编译器不需要特化,直接调用int类型加法函数Add<int>(1, 2); // 使用显示实例化函数,调用编译器特化的Add版本
}

此处可以通过调试进行测试,在第一个函数处打一个断点(F9),然后F11进入函数,就能直接进入int类型的专门函数,显示实例化也是同理。 

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

总结:与非模板函数参数类型完全匹配先调用非模板函数,其余都调用模板函数。


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

3.2、类模板的实例化

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

// Vector类名,Vector<int>才是类型
Vector<int> s1;
Vector<double> s2;

注意:此章节只是大致认识模板,后面会通过STL详细讲解模板的用法。 

总结


本篇博客就结束啦,谢谢大家的观看,如果公主少年们有好的建议可以留言喔,谢谢大家啦!

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

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

相关文章

抽象类和接口(2)(接口部分)

❤️❤️前言~&#x1f973;&#x1f389;&#x1f389;&#x1f389; hellohello~&#xff0c;大家好&#x1f495;&#x1f495;&#xff0c;这里是E绵绵呀✋✋ &#xff0c;如果觉得这篇文章还不错的话还请点赞❤️❤️收藏&#x1f49e; &#x1f49e; 关注&#x1f4a5;&a…

增加网站搜索引擎排名的6个准则

怎样提高网站排名首页 在竞争激烈的网络世界中&#xff0c;网站的排名对于吸引流量和提升曝光至关重要。登上搜索引擎结果页面的首页&#xff0c;意味着更多的曝光和点击率。以下是一些方法&#xff0c;可以帮助您提高网站在搜索引擎中的排名&#xff0c;让其跻身首页&#xf…

2014年认证杯SPSSPRO杯数学建模A题(第二阶段)轮胎的花纹全过程文档及程序

2014年认证杯SPSSPRO杯数学建模 A题 轮胎的花纹 原题再现&#xff1a; 轮胎被广泛使用在多种陆地交通工具上。根据性能的需要&#xff0c;轮胎表面常会加工出不同形状的花纹。在设计轮胎时&#xff0c;往往要针对其使用环境&#xff0c;设计出相应的花纹形状。   第二阶段问…

SAP 销售分销中的免费货物

销售业务中&#xff0c;免费货物在您与客户协商价格时起着重要作用。在零售、化工或消费品这样的行业部门中&#xff0c;通常以免费货物的形式向客户提供折扣。 作为用户&#xff0c;业务用户希望能自动确定免费货物并将它们归入销售凭证中。同时需要向成本控制部门提供免费货物…

SOC内部集成网络MAC外设+ PHY网络芯片方案:PHY芯片基础知识

一. 简介 本文简单了解一下 "SOC内部集成网络MAC外设 PHY网络芯片方案" 这个网络硬件方案中涉及的 PHY网络芯片的基础知识。 二. PHY芯片基础知识 PHY 是 IEEE 802.3 规定的一个标准模块。 1. IEEE规定了PHY芯片的前 16个寄存器功能是一样的 前面说了&#xf…

[优选算法专栏]专题十五:FloodFill算法(二)

本专栏内容为&#xff1a;算法学习专栏&#xff0c;分为优选算法专栏&#xff0c;贪心算法专栏&#xff0c;动态规划专栏以及递归&#xff0c;搜索与回溯算法专栏四部分。 通过本专栏的深入学习&#xff0c;你可以了解并掌握算法。 &#x1f493;博主csdn个人主页&#xff1a;小…

基于8086多路模拟采集LED报警系统设计

**单片机设计介绍&#xff0c;基于8086多路模拟采集LED报警系统设计 文章目录 一 概要二、功能设计设计思路 三、 软件设计原理图 五、 程序六、 文章目录 一 概要 基于8086多路模拟采集LED报警系统设计概要 一、引言 在工业控制、环境监测以及智能家居等领域&#xff0c;多…

探索http-vue-loader的奥秘:原理、使用方法、在Vue开发中的应用

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

软考历史题目

2023.3 1. 磁盘索引块1KB,每个地址项4字节&#xff0c;每个磁盘索引块可以存放256个物理块地址 2.5个地址项为直接索引地址&#xff0c;所以0-5逻辑块是直接索引 3.一级间接地址索引&#xff0c;每个指向的物理块存255个地址 4.二级间接地址&#xff1a;256个间接索引表地址…

碧桂园服务:以进促稳,年收入增长至人民币约426.1亿元

碧桂园服务控股有限公司今日发布截至2023年12月31日十二个月报告期内之经审核综合业绩。2023年&#xff0c;碧桂园服务收入持续增长至人民币约426.1亿元。同时&#xff0c;业务发展保持稳健且市场化程度高&#xff0c;来自于第三方的收入占比进一步提升达到新高至约96.9%。 业绩…

提高编程效率的VScode插件

1.Prettier Prettier 是一种广泛使用的采用代码格式化程序&#xff0c;在您的项目中强制执行一致的代码风格。它支持各种编程语言 并根据预定义的规则自动格式化您的代码&#xff0c;从而增强可读性并减少与样式相关的冲突。 2.远程 SSH Visual Studio Code 的 远程 – SSH…

DSSS-UQPSK学习笔记

文章目录 非平衡四相键控-直接序列扩频&#xff08;UQPSK-DSSS&#xff09;信号因其能同时传输两路不同功率、不同速率信号的特点&#xff0c;在需要图象和数据综合业务传输的领域得到了广泛应用。 系统信号的调制方式为非平衡四相键控&#xff08;Unbalanced Quadrature Phase…

注册接口和前置SQL及数据生成及封装

注册接口 演示注册接口的三步操作&#xff1a;【注册流程逻辑】 第一步&#xff1a;发送注册短信验证码接口请求 请求方法&#xff1a; put 请求地址&#xff1a;http://shop.lemonban.com:8107/user/sendRegisterSms 请求参数&#xff1a;{“mobile”:“13422337766”} 请求头…

​打破牙医恐惧 从牙一齿科开始——记杭州资深口腔专家武建潮博士与他的牙科品牌

生机勃勃的绿植花卉&#xff0c;温馨亲切的原木装修&#xff0c;卡通乐园般的儿童诊室&#xff0c;一应俱全的先进设备……走进位于浙江省杭州市余杭区荆长路590-1-A的牙一齿科&#xff0c;温暖的气息扑面而来&#xff0c;细致热情的服务更让人如沐春风&#xff0c;任谁都很难想…

1.8 python 模块 time、random、string、hashlib、os、re、json

ython之模块 一、模块的介绍 &#xff08;1&#xff09;python模块&#xff0c;是一个python文件&#xff0c;以一个.py文件&#xff0c;包含了python对象定义和pyhton语句 &#xff08;2&#xff09;python对象定义和python语句 &#xff08;3&#xff09;模块让你能够有逻辑地…

Redis 全景图(2)---- 关于 Redis 的三“高”

前言 我们继续写第一篇文章没写完的。其实我也不想将我写的一篇 Redis 文章分成几篇中短文来写&#xff0c;但是没办法&#xff0c;我一次写个1万字&#xff0c;会限流&#xff0c;所以将就一下吧。 上篇文章我用了 Redis 的6大模块这个思路来描绘我脑子中的 Redis。其实这6大…

密码算法概论

基本概念 什么是密码学&#xff1f; 简单来说&#xff0c;密码学就是研究编制密码和破译密码的技术科学 例题&#xff1a; 密码学的三个阶段 古代到1949年&#xff1a;具有艺术性的科学1949到1975年&#xff1a;IBM制定了加密标准DES1976至今&#xff1a;1976年开创了公钥密…

Golang | Leetcode Golang题解之第4题寻找两个正序数组的中位数

题目&#xff1a; 题解&#xff1a; func findMedianSortedArrays(nums1 []int, nums2 []int) float64 {if len(nums1) > len(nums2) {return findMedianSortedArrays(nums2, nums1)}m, n : len(nums1), len(nums2)left, right : 0, mmedian1, median2 : 0, 0for left <…

app自动化-Appium学习笔记

使用Appium&#xff0c;优点&#xff1a; 1、支持语言比较多&#xff0c;例如&#xff1a;Java、Python、Javascript、PHP、C#等语言 2、支持跨应用&#xff08;windows、mac、linux&#xff09; 3、适用平台Android、iOS 4、支持Native App(原生app)、Web App、Hybird App…

算法系列--递归,回溯,剪枝的综合应用(1)

&#x1f495;"对相爱的人来说&#xff0c;对方的心意&#xff0c;才是最好的房子。"&#x1f495; 作者&#xff1a;Lvzi 文章主要内容&#xff1a;算法系列–递归,回溯,剪枝的综合应用(1) 大家好,今天为大家带来的是算法系列--递归,回溯,剪枝的综合应用(1) 1.全排…