探索C嘎嘎:模版初阶

前言:

  小编在前文讲述了C++的内存管理,下面我们来开始继续探索C++,开启C++又一个重要的内容,模版初阶的详解,代码时间到!


目录

1.泛型编程

1.1.引子

1.2.泛型编程

2.函数模版

2.1.函数模版的概念

2.2.函数模版的格式

2.3.函数模版的原理

2.4.函数模版的实例化

 2.4.1.隐式实例化

2.4.2.显示实例化

2.5.函数模版的匹配原则

3.类模版

3.1.类模版的定义格式

3.2.类模版的实例化

4.总结
​​​​​​​


正文:

1.泛型编程

1.1.引子

  在讲述泛型编程之前,小编先说一个例子来帮助各位读者朋友等会更好的去了解泛型编程,交换函数想必各位读者朋友都非常清楚,我们在C语言阶段就多次写过交换函数,小编也在二叉树那篇文章也写过交换函数,交换函数是帮我们去交换两个数,只不过这两个数的类型一般是一致的,就比如整形就得和整形进行交换,字符型就是要和字符型进行交换,就比如下面代码所示:

void swap(int& a, int& b)
{int c = a;a = b;b = c;
}
void swap(float& a, float& b)
{float c = a;a = b;b = c;
}
void swap(char& a, char& b)
{char c = a;a = b;b = c;
}

  当我们在写一个项目的时候,那个项目既有整形的交换,浮点型的交换,字符型交换等等,这就意味着我们需要写三个重载的函数来完成交换函数,这样就体现不出来C++的简介美了,只会让我们增加写代码的量,而且还有代码的可维护性比较低,一步错步步错,这就得不偿失了,于是C++就推出了一个好用的功能,它就是模版,通过写模版我们就可以实现出交换函数,一个模版便可以解决上面三个函数的问题2,在具体讲解模版之前,小编先给各地读者朋友简单介绍一下泛型编程。

1.2.泛型编程

  如果在C++中,也能存在一个摸具,通过给这个模具不断的添加材料(类型),来获得不同材料的铸件(即生成相同类型的代码),那就会节省很多开支,巧的就是前人已经将树栽好(模具已经建立),我们仅需再次乘凉即可。泛型编程就是编写与类型无关的通用代码,是代码复用的一种手段,我们今日所讲的模版,便就是泛型编程的基础,现在我们还不能完全去了解泛型编程,因为我们学的还没有那么深,现在我们仅需知道模版是泛型编程的基础即可,下面小编将会分两步进行模版的讲述,一个是函数的模版,一个是类的模版,下面,系好安全带,准备出发!

2.函数模版

2.1.函数模版的概念

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

2.2.函数模版的格式

  下面小编就展示一下我们如何去写函数模版,如下所示:

template<typename T1, typename T2,......,typename Tn>
返回值类型 函数名(参数列表){}  //这里需要注意,此时上面的typename也可以写成class,怎么方便怎么来

  以上便就是函数模版的写法,小编也在代码页写了,此时的typename也可以写成class,根据自己的习惯自己来就好,小编就喜欢使用class,可能现在很多读者朋友知道了用法,但是不知道如何实践,不要着急,下面小编就给各位读者朋友展示一下交换函数的模版应该怎么写。

template<class T>
void swap(T& x, T& y)
{T m = x;x = y;y = m;
}

  上面便就是交换函数的模版,通过上面的书写,小编认为可以快速帮助读者朋友认识到函数模版的使用,下面小编给各位读者朋友讲述一下函数模版实现的原理。

2.3.函数模版的原理

  函数模版其实和现实生活中的蓝图差不多,它本身并不是函数,是编译器用使用方式产生特定的具体类型的模具,所以其实模版就是帮助我们把本来我们自己要重复干的活交给了编译器来做,简单来说,我们通过模版让编译器变成了牛马,其中的过程如下图所示:

   在编译器进行编译的阶段,对于函数模版的使用,编译器需要根据传入的实参类型来推演生成对应类型的函数以供调用。就比如:当用double类型使用函数模版的时候,编译器会对类型进行推演,进而确认T就是double,然后会产生一份专门处理double的代码,对于字符型,整形什么的也是这种情况,这就是函数模版的原理,简单来说,我们只要写好了模版,编译器会自动识别我们传递的类型从而把T转换成对应的类型,这个时候可能就有读者朋友会问了,对于上面小编所写的交换函数代码,倘若我填的第一个数是整形,第二个数是浮点型会有怎样的情况?不要着急,这涉及到了小编后面将会讲述的知识点,下面继续往后出发喽!

2.4.函数模版的实例化

  用不同的类型使用函数模版的时候,称为函数模版的实例化,函数模版的实例化可以分为隐式实例化和显示实例化,现在我们先来进行前者的讲述。

 2.4.1.隐式实例化

  对于隐式实例化,说白了其实就是让编译器自己去识别此时的类型是什么,然后再把T转换成相应的类型即可,下面小编就用加法函数来给各位读者朋友举例,如下代码所示:

template<class T>
T Add(T x, T y)
{return x + y;
}
int main()
{int a = 12, b = 13;double c = 11.1, d = 12.2;int m = Add(a,b);Add(c, d);
}

  以上就是函数模版的隐式实例化,其实隐式实例化可以理解为我们什么也不需要做,让编译器帮我们去做就好了,不过此时的隐式实例化有一个情况倘若我们什么也不做是行不通的,就比如下面的实例化:

Add(a, d);

   此时如果这么写的话编译器是给我们报错的,编译器报错的原因解释的不太行,这里小编提一嘴,报错后编译器给出的错误并不是完全正确的,有时候也是会有出错的情况,这里出错的原因其实就是此时的编译器是无法理解此时我们传的类型到底是什么,如果是按照第一个参数来断定T的类型,那么在第二个参数的时候便会出错,这让编译器摸不着头脑了,对于这个问题的解决策略,小编有两种解法可以帮助我们去把这个题目解决,如下所示:

1.把某一个元素强制类型转换(简单粗暴)

Add(a, (int)d);

2. 再写一个模版,不过此时的模版参数是两个,如下所示:

template<class T1,class T2>
T1 Add(T1 x, T2 y)
{return x + y;
}

  对于第一种解决方案,小编认为还是蛮简单粗暴的,我们仅需随机在两个实参中把其中一个进行强制类型转换,从而让编译器不在犯迷糊,这是是用一个模版参量解决的方案之一,等会再显示类型转换的时候小编还会继续说,对于第二种方式,从严格意义上来讲,这是牵扯到了另一个模版了,如果我们在写题目的时候强制只有一个模版参量,那么就用第一个就可以了,反之使用第二个就好了,这便是隐式实例化的内容,下面开始讲解显示实例化。

2.4.2.显示实例化

  对于显示实例化,它的用法也是很简单,我们仅需在函数名后加上<>即可,<>里面放置的是我们想要模版参数类型的实际类型,还是拿上面的整形和浮点型相加来进行举例,如果我们仅写一个模版参量的模版,那么强制类型转换是第一种解决方案,显示实例化则是第二种解决方案,如下所示:

Add<int>(a, d);

  上面的代码就可以成功的去运行,因为此时我们使用了显示实例化,我们直接告诉了编译器,此时的模版参量就是int类型,编译器会在传参的过程中默默会生成隐式类型转换,把其中不是整形的转换为整形的,这就是显示类型实例化,难度也没有很大,各位读者朋友要知道这些实例化的方法,避免以后框框出错,下面我们进入函数模版最后一部分的讲解。

2.5.函数模版的匹配原则

  肯定有读书朋友好奇,倘若我在写Add函数的时候,我写了一份整形类型的Add函数,写了一份单参量的函数模版,还写了一份双模版的函数模版,那么如果我调用Add(1,2),那么编译器会先去调用哪一份函数呢?不要着急,下面小编就介绍一下函数模版的匹配原则:

 1.一个非模版函数可以和一个同名的函数模版同时存在,而且该函数模版还可以被实例化为这个非模版函数。这个说法是很容易让人去理解的,它意味着我们写完了一个模版Add以后,还可以写一个专属整型的Add函数,这俩是可以同时存在的,当这两个同时存在时,倘若我写了一个Add(1,2),编译器是会去调用整型的Add函数,而不会去使用模版,对于这个特点小编会在下面说的,这里我提前说一下,我们可以把模版想成菜单,把专属整型的Add函数认定为预制菜,编译器也不傻,有预制菜不用去用菜单自己炒一个,所以会去调用后面的函数,如下图所示:

int Add(int x, int y)
{return x = y;
}
template<class T>
T Add(T x, T y)
{return x + y;
}
int main()
{int a = 12, b = 13;Add(a, b);
}

  上图就显示了编译器是会调用现成的函数的,这就引出了第二个特点:

 2.对于非模版函数和同名函数模版,如果其他条件都相同,在调用时会优先调用非模版函数而不会从该模版产生出一个实例,如果模版可以产生一个具有更好匹配的函数,那么还是会选择模版。这个特点小编也在前面说了,编译器又不是傻子,它虽然是一个牛马,但它知道如何做才会省事,所以它是会筛选模版函数的,就比如我写了两个模版参量的模版和一个模版参量的模版,如果我用了Add(1,2),那么是会去调用一个参量的,因为省事,但是如果我是Add(1,1.1),那么系统会直接调用两个模版参量的,如下所示:

template<class T>
T Add(T x, T y)
{return x + y;
}
template<class T1,class T2>
T1 Add(T1 x, T2 y)
{return x + y;
}
int main()
{int a = 12, b = 13;double c = 11.1, d = 12.2;Add(a, b);Add(a, d);
}

  上面的调试过程便给我们展示了函数模版是如何去进行调用的,如果都是一个类型,编译器是会调用单模版参量的模版,因为省事,仅需把一个T转换为一个类型即可;如果有两个类型,那么自然的就会去调用两个模版参量的模版,这就是第二个匹配原则,下面来看第三个:

 3.函数模拟不允许自动类型转换,但是普通函数可以进行自动类型转换。这个特点小编在上面也就展示出来了,这里就不多说明了,这就是函数模版的写法,下面我们继续出发,开始讲述类模版的写法~

3.类模版

3.1.类模版的定义格式

  其实函数模版就已经讲述了许多模版的特性了,所以在类模版的时候小编会少说一点知识点,不然就显的我水字数了,下面小编就通过写代码的方式来帮助读者朋友知道类模版的定义格式:

template<class T1,class T2>  //不一定就这些
class wang
{//类内成员函数的定义或者类内成员的定义
};

  上面就是类模版的定义格式,下面小编就以Stack类模版来帮助各位更好的去理解类模版:

template<class T>
class Stack
{
public:Stack(int capcaity = 4){_arr = new Stack[capcaity];_size = 0;_capcaity = capcaity;}
private:T* _arr;int _capcaity;int _size;
};

   上面就是小编简单写出来的Stack类模版,其实类模版和函数模版是很像的,只不过一个是函数一个类罢了,想必现在很多读者朋友会好奇类模版如何实例化,不要着急,下面小编就给各位读者朋友讲述一下类模版的实例化。

3.2.类模版的实例化

  类模版的实例化和函数模版的实例化不同,类模版的实例化需要在类模版后面加上<>,然后将实例化对象的类型放在<>即可,简单来说类模版只可以显示实例化,因为如果不这样干的话编译器不知道如何去进行实例化,类模版的名字并不是真正的类,而实例化的结果才是真正的类,下面小编就给出类模版实例化的代码:

int main()
{Stack<int>s1; //这样实例化可以额Stack s2;  //这样实例化会报错,报错原因:缺少 类模板 "Stack" 的参数列表
}

  对于类模版的实例化,就必须显示实例化,这个点各位读者朋友一定要记住,以上就是类模版的讲解,讲解的还是蛮少的,因为函数模版其实就把模版的一些特性讲述的很多了,类模版的讲述仅仅就是帮助读者朋友去了解类模版的使用罢了。

4.总结

  以上就是本篇博客小编所要讲述的内容,模版是C++比较重要的内容,也是一个为后面知识学习打下的基础,小编之后就要开始讲解STL库了,到时候将会给读者朋友们展示一下C++内容最爽的部分,如果本篇文章出现错误,请在评论区指出,小编定会及时回复,那么,大佬们,我们下一篇文章见啦!(牙疼真要命)

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

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

相关文章

基于知识图谱的电子元器件问答系统

你还在为寻找电子元器件的相关信息头疼吗&#xff1f;作为一名程序员或电子工程师&#xff0c;在项目中经常需要快速查询电子元件的属性或关联关系。今天给大家介绍一个可以大大提升工作效率的神器——基于知识图谱的电子元器件问答系统。这不仅是你学习和工作的好帮手&#xf…

解读华为云Kuasar多沙箱容器技术,带来更强隔离性和安全性

摘要&#xff1a;沙箱技术的引入&#xff0c;为容器提供了更强的隔离性和安全性&#xff0c;成为云原生技术的重要组成部分。 本文来源 《华为云DTSE》第五期开源专刊&#xff0c;作者&#xff1a;华为云云原生开源团队研发工程师。 近年来&#xff0c;云原生容器技术飞速发展&…

详解Java之异常

目录 防御式编程 捕获异常 基础语法 示例1 【不处理异常】 示例2 【使用try catch捕获异常】 示例3 【catch只能处理对应的异常】 示例4 【catch可以有多个】 示例5 【可以用一个catch捕获所有异常】 示例6 【finally一定会执行】 示例7 【使用try回收资源】 示例8 …

鸿蒙网络编程系列24-Web组件与应用互操作示例

1. APP内嵌网页与应用互操作概述 在通常的APP开发中&#xff0c;经常会采用内嵌网页的形式&#xff0c;通过网页来展现丰富的动态内容&#xff0c;虽少了很多原生开发的功能&#xff0c;但是这么做无可厚非&#xff0c;毕竟APP需要适配的系统平台很多&#xff0c;比如安卓、苹…

【HarmonyOS NEXT】权限申请及应用设置页跳转

关键词&#xff1a;鸿蒙、程序访问控制、定位、应用详情页、startability、want 在app开发过程中&#xff0c;常进行系统权限的申请以提供设备访问或个性化功能&#xff08;如扫一扫、城市定位、剪贴板等&#xff09;&#xff0c;从而保障应用功能的完整性&#xff0c;那么本期…

Jupyter notebook和Conda使用

Jupyter notebook和Conda使用 文章目录 Jupyter notebook和Conda使用AnacondaJupyter notebook简介页面使用技巧编写格式自动补全查看函数文档魔术命令远程访问交互式 Anaconda Anaconda是一个开源的Python发行版本&#xff0c;其包含了conda、Python等180多个科学包及其依赖项…

stm32实现esp8266连接到TCP服务器(二)未完

1.2 连接到TCP Server 1.2.1 使用网络助手&#xff0c;设立TCP服务器 ​ 编辑 1.2.2 连接服务器 ATCIPSTART"TCP","192.168.1.18",8080 //指令&#xff0c;注意双引号逗号都要半角(英文)输入 CONNECT //结果&#xff1a;成功 OK //结果&#xff1a;成功 …

jmeter中用csv data set config做参数化2

在jmeter中&#xff0c;使用csv data set config进行参数化是很重要的一个功能&#xff0c;但是这个功能的使用需要十分仔细和小心&#xff0c;因为细节之处往往决定着结果的正确与否。 举例&#xff1a; 一个登录接口用加密密码登录&#xff0c;一个登录接口用原始密码登录。…

STM32G4系列MCU的低功耗模式介绍

目录 概述 1 认识低功耗模式 1.1 低功耗模式的应用 1.2 低功耗模式介绍 2 低功耗模式的状态关系 2.1 低功耗模式可能的转换状态图 2.2 低功耗模式总结 3 运行模式 3.1 减慢系统时钟 3.2 外围时钟门控 3.3 低功耗运行模式&#xff08;LP运行&#xff09; 概述 本文主…

JavaFx学习--chapter02(网络对话)

chapter02(网络对话) 简单网络对话程序 设计任务&#xff1a;客户端向服务器发送字符串&#xff0c;并能读取服务器返回的字符串。 知识点&#xff1a;TCP套接字技术&#xff0c;C/S软件架构程序设计 重点理解&#xff1a;Java客户套接字类Socket和服务器套接字类ServerSoc…

蜜罐技术的出现究竟影响了什么

自网络诞生以来&#xff0c;攻击威胁事件层出不穷&#xff0c;网络攻防对抗已成为信息时代背景下的无硝烟战争。然而&#xff0c;传统的网络防御技术如防火墙、入侵检测技术等都是一种敌暗我明的被动防御&#xff0c;难以有效应对攻击者随时随地发起的无处不在的攻击和威胁。蜜…

linux线程 | 同步与互斥 | 互斥(下)

前言&#xff1a;本篇文章主要讲述linux线程的互斥的知识。 讲解流程为先讲解锁的工作原理&#xff0c; 再自己封装一下锁并且使用一下。 做完这些就要输出一堆理论性的东西&#xff0c; 但博主会总结两条结论&#xff01;&#xff01;最后就是讲一下死锁。 那么&#xff0c; 废…

什么是 Idempotence 以及它在哪里使用?

大家好&#xff0c;我是锋哥。今天分享关于【什么是 Idempotence 以及它在哪里使用&#xff1f;】面试题&#xff1f;希望对大家有帮助&#xff1b; 什么是 Idempotence 以及它在哪里使用&#xff1f; 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 Idempotence&am…

【C++STL】list的基本介绍与使用方式

✨ Blog’s 主页: 白乐天_ξ( ✿&#xff1e;◡❛) &#x1f308; 个人Motto&#xff1a;他强任他强&#xff0c;清风拂山冈&#xff01; &#x1f525; 所属专栏&#xff1a;C深入学习笔记 &#x1f4ab; 欢迎来到我的学习笔记&#xff01; 一、list的介绍 文档内容以及大致翻…

ESP32-IDF 非易失存储 NVS

目录 零、前言一、基本介绍1、配置结构体1.1 nvs_entry_info_t 2、常用 API2.1 nvs_flash_init2.2 nvs_flash_init_partition2.3 nvs_flash_init_partition_ptr2.4 nvs_flash_erase2.5 nvs_flash_erase_partition2.6 nvs_flash_erase_partition_ptr2.7 nvs_flash_generate_keys…

element plus中menu菜单技巧

我在使用element plus的menu&#xff08;侧边栏&#xff09;组件的过程中遇到了一些问题&#xff0c;就是menu编写样式和路由跳转&#xff0c;下面给大家分享以下&#xff0c;我是怎么解决的。 1.页面效果 我要实现的网站布局是这样的&#xff1a; 侧边栏折叠以后的效果&#…

python爬虫快速入门之---Scrapy 从入门到包吃包住

python爬虫快速入门之—Scrapy 从入门到包吃包住 文章目录 python爬虫快速入门之---Scrapy 从入门到包吃包住一、scrapy简介1.1、scrapy是什么?1.2、Scrapy 的特点1.3、Scrapy 的主要组件1.4、Scrapy 工作流程1.5、scrapy的安装 二、scrapy项目快速入门2.1、scrapy项目快速创建…

详解equals底层原理

equals 方法是 Java 中用于比较两个对象是否“相等”的方法。在 Java 中&#xff0c;每个类都继承自 java.lang.Object 类&#xff0c;而 equals 方法正是定义在 Object 类中的一个方法。默认情况下&#xff0c;Object 类的 equals 方法比较的是两个对象的内存地址&#xff08;…

SQL 多表联查

SQL JOIN (w3school.com.cn) SQL join用于根据两个或多个表中的列之间的关系&#xff0c;从这些表中查询数据。 之前跟着老师学数据库的时候学过&#xff0c;最近又在比较频繁的使用&#xff0c;再复习一下。 Person表&#xff1a; Id_P &#xff1a;居民编号。主键 …

大数据开发基于Hadoop+springboot平台的岗位推荐系统

文章目录 前言项目介绍技术介绍功能介绍核心代码数据库参考 系统效果图文章目录 前言 文章底部名片&#xff0c;获取项目的完整演示视频&#xff0c;免费解答技术疑问 项目介绍 随着网络科学技术不断的发展和普及化&#xff0c;用户在寻找适合自己的信息管理系统时面临着越来…