C++学习指南(三)——模板

news2024/9/22 7:28:12

欢迎来到繁星的CSDN。本期内容主要包括模板template。

目录

一、什么是模板?

      

二、函数模板

      模板的定义方式

      模板的实例化(确定参数的类型)

       隐式实例化

       显式实例化

       实例化顺序

三、类模板和模板类

      类模板的实例化


一、什么是模板?

        

    模板,工业生产上用以注塑、吹塑、挤出、压铸或锻压成型、冶炼、冲压等方法得到所需产品的各种模子和工具。 简而言之,模板是用来制作成型物品的工具,这种工具由各种零件构成,不同的模板由不同的零件构成。它主要通过所成型材料物理状态的改变来实现物品外形的加工。素有“工业之母”的称号。

        不得不说,模板是工业上是堪比轮子的发明。

   而C++中,模板也正是我们“量产”代码,复用代码的关键。

template<class T>
void swap(T& a, T& b) {
	T tmp=a;
	a = b;
	b = tmp;
}

    如图,便是一个简单的swap函数,它支持任何两个同一类型的变量进行交换。

    (这里的swap改为大写的原因是,C++<iostream>库里有相同的swap函数,为了不影响演示,所以改了函数名字)

        但当我们输入的a和b类型不同的时候,系统会报错。

        这个问题先按下不表,等讲完函数模板,也就清晰了。

      

二、函数模板

        在刚刚的错误列表中,我们发现了函数模板字样。而事实上,模板分为函数模板和类模板。这一部分先叙述函数模板,因为函数模板往往是类模板的一个组成部分。

      模板的定义方式

        template的相关内容当然没有这么少。

template<class T1, class T2,.....>
(返回值类型)(函数名)(形参){
    //write code here
}

    模板关键字template可以同时定义多个虚拟类型的参数,T1,T2等等,程序员可以在这里写上百个参数,但在后面的模板里,你必须用到这些参数,否则编译器会报错。

        

    定义虚拟类型的关键字是typename或者class,这两种都可以且可以混用,但不能用struct!

     

    而对于同一个虚拟类型参数而言,编译器会在编译使其实例化的时候,让同一个虚拟参数全部编译为某一类型。

        所以,如果将代码按如下改造,便可以使得模板更灵活。

template<class T1,class T2>
void Swap(T1& a,T2& b){
    T1 tmp=a;
    a=b;
    b=tmp;
}

        因为T1和T2可以不为同一类型,也可以是同一类型,所以在语法层面上来说,没有错误。

        但很抱歉的是,如果这么写,无法得到真正的转换。(尽管这是函数的问题,而非模板)

      模板的实例化(确定参数的类型)

        模板的实例化分为两类:隐式实例化,显示实例化。

       隐式实例化

   隐式实例化我们实际上已经演示过了,上图的Swap就是隐式实例化。

   在函数编译的时候,编译器会通过我们传入的参数的类型,来“猜”对应的虚拟类型是什么。

   如果发现猜不到类型(如对着同一个虚拟类型传入了两个不同类型的参数),编译器会开始查看是否有其他的重载函数。因为除了模板,普通函数也是可以重载的。

    这两步都做完,如果还找不到,那么编译器就会报错。

      

       显式实例化

        

template<class T1,class T2>
void Swap(T1& a, T2& b) {
	T1 tmp=a;
	a = b;
	b = tmp;
}

int main() {
	int a = 10;
	double b = 9.9;
	Swap<int,double>(a, b);
	cout << "a:" << a << endl;
	cout << "b:" << b << endl;
	return 0;
}

   观察调用Swap的时候,我们在Swap函数后加入了<int,double>,代表第一个参数是int,第二个参数是double(但仍然需要定义两个虚拟类型)

        如果只需要一个参数类型,也可以这么写:

Swap<int>(a,b);

        这就意味着将b强制类型转换为int。

        当显式实例化不成功,编译器会尝试自己匹配类型(隐式实例化)。

       实例化顺序

   1、一个非模板函数可以和一个同名的函数模板同时存在,而且该函数模板还可以被实例化为这个非模板函数。

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

        最容易的理解方式是:

        模板是参数相同的同名函数的一个总和,这意味着普通函数,也可能是某一模板的实例化。

        模板实例化出一个函数是需要消耗资源的,编译器会优先使用已有的模板函数,但如果在匹配上,模板实例化出的函数更匹配,那么就会用模板。这和我们之前提到的引用返回还是传值返回的原则很像,先达成目的,再考虑效率

   需要注意的一点是:

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

三、类模板和模板类

        类模板,本质还是模板,只不过是某一种类的模板,因而称为类模板。其实例化产生的类,称为模板类。这两个名字经常容易混淆,实际上只需要看后缀,一个本质是模板,一个本质是类。

        类模板的定义格式如下:

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

         需要注意的是,类模板中函数在类外定义时,需要加模板参数列表。(声明与定义分离的情况),所以在练习的时候,为了避免不必要的麻烦,尽量在类内定义。工作中可能因为需要时常维护,导致需要分离定义。

// 注意:类模板中函数放在类外进行定义时,需要加模板参数列表
template <class T>
Vector<T>::~Vector()
{
 if(_pData)
 delete[] _pData;
 _size = _capacity = 0;
}

      类模板的实例化

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

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

        (这里大写的原因,仍然是因为vector在C++中有特殊含义,后续会讲到)。

        本篇内容到此结束,谢谢大家的观看!

        觉得写的还不错的可以点点关注,收藏和赞,一键三连。

        我们下期再见~

        往期栏目:    

        C++学习指南(一)——C++入门基础-CSDN博客

        C++学习指南(二)——类和对象-CSDN博客    

        

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

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

相关文章

智慧职校就业管理:开启校园招聘会新模式

在智慧职校的就业管理系统中&#xff0c;校园招聘会的出现&#xff0c;为学生们提供了一个展示自我、探寻职业道路的舞台&#xff0c;同时也为企业搭建了一座直面未来之星的桥梁。这一功能&#xff0c;凭借其独特的优势与前沿的技术&#xff0c;正在重新定义校园与职场之间的过…

2024中国大学生算法设计超级联赛(1)

&#x1f680;欢迎来到本文&#x1f680; &#x1f349;个人简介&#xff1a;陈童学哦&#xff0c;彩笔ACMer一枚。 &#x1f3c0;所属专栏&#xff1a;杭电多校集训 本文用于记录回顾总结解题思路便于加深理解。 &#x1f4e2;&#x1f4e2;&#x1f4e2;传送门 A - 循环位移解…

python-爬虫实例(5):将进酒,杯莫停!

目录 前言 将进酒&#xff0c;杯莫停&#xff01; 一、浇给 二、前摇 1.导入selenium库 2.下载浏览器驱动 三、爬虫四步走 1.UA伪装 2.获取url 3.发送请求 4.获取响应数据进行解析并保存 总结 前言 博主身为一个农批&#xff0c;当然要尝试爬取王者荣耀的东西啦。 将进…

萝卜快跑突然就火了,背后发生了什么?

近日&#xff0c;百度旗下的自动驾驶出行平台“萝卜快跑”突然在网络上火了起来&#xff0c;成为热门话题。那么&#xff0c;这背后到底发生了什么&#xff1f; 1. 数字误传引发热议 首先&#xff0c;一些误传的数字在传播中起到了推波助澜的作用。例如&#xff0c;百度在2023…

【北京迅为】《i.MX8MM嵌入式Linux开发指南》-第三篇 嵌入式Linux驱动开发篇-第三十八章 驱动模块编译进内核

i.MX8MM处理器采用了先进的14LPCFinFET工艺&#xff0c;提供更快的速度和更高的电源效率;四核Cortex-A53&#xff0c;单核Cortex-M4&#xff0c;多达五个内核 &#xff0c;主频高达1.8GHz&#xff0c;2G DDR4内存、8G EMMC存储。千兆工业级以太网、MIPI-DSI、USB HOST、WIFI/BT…

PCL 批量处理点云文件

系列文章目录 文章目录 系列文章目录前言一、PCL是什么&#xff1f;二、配置PCL环境三、使用步骤1.引入库2.主函数 总结 前言 点云处理时往往会需要对多个点云进行处理&#xff0c;比如在预处理&#xff0c;保存点云时。下面提供一个简单的点云批量转换例子&#xff0c;PCD文件…

MongoDB 文档存储

安装 下载&#xff1a; Download MongoDB Community Server | MongoDB 说明&#xff1a; 现在基本都安装的是4.4以后的版本。安装完成后使用 mongod 来查看是否安装成功 会输出一堆内容 而如果想要操作数据库&#xff0c;则需要安装一个工具&#xff0c;mongosh-2.2.12-x64.m…

JavaSE从零开始到精通(七) - Stream流

1. 概述 Java 8引入了Stream API&#xff0c;它提供了一种高效且易于使用的处理集合数据的方式。Stream流可以被认为是一种高级的迭代器&#xff0c;允许我们在集合上进行复杂的操作&#xff0c;例如过滤、映射、排序、归约等&#xff0c;而这些操作可以链式调用&#xff0c;形…

C# 开发监控方法执行耗时

MethodTimer.Fody 是一个功能强大的库,可以用于测量 .NET 应用程序中的方法的执行时间。允许你在不修改代码的情况下,自动地测量和记录方法的执行时间。 这个工具是基于.NET的 weaving 技术,通过修改IL(Intermediate Language,中间语言)代码来插入计时逻辑,从而在方法调…

Python内存管理:引用计数与垃圾回收

✨ 内容&#xff1a; 在Python中&#xff0c;内存管理是一个重要且常常被忽视的话题。了解Python如何管理内存&#xff0c;不仅能帮助我们编写高效的代码&#xff0c;还能避免潜在的内存泄漏问题。今天&#xff0c;我们将通过一个实际案例&#xff0c;深入探讨Python的内存管理…

MIT6.824(6.5840) Lab1笔记+源码

文章目录 其他人的内容&#xff0c;笔记写的更好&#xff0c;思路可以去看他们的MapReduceworkermapreduce coordinatorrpc纠错 源码worker.gocoordinator.gorpc.go 原本有可借鉴的部分 mrsequential.go&#xff0c;多看几遍源码 其他人的内容&#xff0c;笔记写的更好&#xf…

如何实现ORACLE19c 安装包DIY

最近一直忙&#xff0c;本想每周有更新的&#xff0c;但老板一句话&#xff0c;就得去干活&#xff0c;想实现这个愿望&#xff0c;看来真的很难&#xff0c;做一天好人容易&#xff0c;要一辈子做好人&#xff0c;难。所以&#xff0c;看到德哥&#xff0c;尹总监&#xff0c;…

言语理解与表达

** 言语理解与表达 1.逻辑填空 2.语句表达 3.阅读理解

MTK 安卓14 launcher3修改桌面模式,替换某些应用图标,以及定制化Hotseat

原生的launcher的Hotseat如下图(1)所示,我想把效果改成图(2) 图(1) 图(2) 一:定制化HotSeat 修改的类&#xff1a;packages/apps/Launcher3/com/android/launcher3/Hotseat.java &#xff08;1&#xff09;.修改hotseat的宽 Hotseat------->setInsetsOverridepublic void…

Java 22 中的4个永久特性

功能处于孵化或预览阶段是什么意思&#xff1f; 实际上&#xff0c;这是向 Java 编程语言添加新功能的新过程&#xff0c;Java 社区使用这种过程来在 API 和工具处于早期实验阶段时从社区获得反馈&#xff08;孵化功能&#xff09;或已经完全指定但尚未永久的阶段&#xff08;…

ConstraintLayout属性说明

ayout_constraintTop_toTopOf&#xff1a;将某一控件的顶部与另一控件的顶部对齐。 layout_constraintTop_toBottomOf&#xff1a;将某一控件的顶部与另一控件的底部对齐。 layout_constraintBottom_toTopOf&#xff1a;将某一控件的底部与另一控件的顶部对齐。 layout_cons…

3GPP R18 Multi-USIM是怎么回事?(四)

前几篇主要是MUSIM feature NAS 部分内容的总结,这篇开始看RRC部分相关的内容,由于RRC部分内容过长,也分成了2篇。这篇就着重看下musim gap以及RRC触发UE离开RRC Connected mode相关的内容,直入正题, 上面的内容在overview中有提到,对应的是如下38.300中的描述。 处于网络…

【Node.js基础02】fs、path模块

目录 一&#xff1a;fs模块-读写文件 1 加载fs模块对象 2 读制定文件内容文件 3 向文件中写入内容 二&#xff1a;path模块-路径处理 1 问题引入 2 __dirname内置变量 使用方法 一&#xff1a;fs模块-读写文件 fs模块封装了与本机文件系统交互方法和属性 1 加载fs模块…

Win11 改造

记录一些安装 win11 系统之后&#xff0c;对使用不习惯的地方&#xff0c;进行的个人改造 右键菜单 Hiyoung006/Win11Useable: 将Win11右键菜单及资源管理器恢复为Win10样式的脚本 切换到旧版右键菜单&#xff1a; reg add "HKCU\Software\Classes\CLSID\{86ca1aa0-34…

Chapter18 基于物理的渲染——Shader入门精要学习

Chapter18 基于物理的渲染 一、PBS理论和数学基础1.光是什么微表面模型 2.渲染方程3.精确光源4.双向反射分布函数 BRDF5.漫反射项&#xff08;Lambert 模型&#xff09;Lambertian BRDF为&#xff1a;Disney BRDF中漫反射项 6.高光反射项微面元理论BRDF的高光反射项①菲涅尔反射…