C++之模板

目录

泛型编程

模板

函数模板

函数模板的实例化

隐式实例化 

显示实例化

类模板


我们知道STL(标准模板库)是C++学习的精华所在,在学习STL之前我们得先学习一个新的知识点-------模板。那么模板究竟是什么呢?围绕着这个问题,进入我们本期的内容。

泛型编程

在学习模板之前我们得先了解什么是泛型编程?

大家可以先想想生活中的一个场景,比如说临近过年了,我们一般在大年夜要吃饺子,要吃饺子,饺子皮必然是必不可少的,比如要包100个饺子,一般情况下我们就得擀上100个饺子皮,但是这样是很费时间的,有没有什么好得方法呢?有人就想到了用一个圆形的模具,使用了圆形的模具之后,生成饺子皮的效率就高了很多了。

当然,上面的场景只是生活中的场景,我们来看看C++中的场景,比如说现在我们要进行两个数的交换,我们一般会写一个交换函数。假设这两个数的类型为int,char,double。相关的代码如下:

void Swap(int& a, int& b)
{int tmp = a;a = b;b = tmp;
}
void Swap(char& a, char& b)
{char tmp = a;a = b;b = tmp;
}
void Swap(double& a, double& b)
{double tmp = a;a = b;b = tmp;
}

我们发现上述三个交换函数就只有类型不同,其它的都是相同的,如果要交换的变量的类型很多时,难道我们也要写这么多的函数吗?有没有一种方法可以改变解决这种情景呢?在C语言中这种情景确实没有很好的解决办法,因为C语言是不支持泛型编程的,但是C++是支持泛型编程的,我们提出了模板这一概念,可以很好的解决这一情景带来的问题。

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

模板

模板分为函数模板和类模板。

注意:在函数中我们将函数括号中的参数称作形参,在函数模板这里我们将尖括号中的称作模板参数。

函数模板

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

注意:在函数中我们将函数括号中的参数称作形参,在函数模板这里我们将尖括号中的称作模板参数。 

 所以对于上面交换三种类型变量的函数我们可以用函数模板实现,代码如下:

template<class T>  
void Swap(T& a, T& b)
{T tmp = a;a = b;b = tmp;
}
int main()
{int a = 10, b = 20;double c = 10.1, d = 9.3;char ch1 = 'a', ch2 = 'b';Swap(a, b);Swap(c, d);Swap(ch1, ch2);return 0;
}

 运行截图:

通过函数模板,不难发现,不同类型的变量确实发生了交换。

但是大家思考一个问题。这三次交换,调用的是同一个函数吗?我们通过底层代码为大家展现:

 很明显,这三次调用不是同一函数,因为函数参数列表的参数类型不同,函数的地址也是不同的。这其中到底发生了什么?

其实,这里发生了函数模板的实例化。我们将实参传给形参之后,编译器会根据我们实参的类型生成对应的函数模板,这相比之前我们手动实现函数,提高了效率。

函数模板的实例化

所谓函数模板的实例化,就是再调用函数模板时,编译器通过传递的实参的类型推导对应类型的函数,然后将实参传递给所推导的函数的形参。这就是函数模板的实例化。

隐式实例化 

隐式实例化:就是我们在调用函数模板时,编译器会根据我们传递的实参的类型自动推导函数模板中的模板参数类型。

注意:隐式实例化时,我们不能让传递的实参为两种类型,因为函数模板中只有一个模板参数,当模板参数只有一个时,一次函数调用只能实例化一种类型,这是如果传递了两种类型,就会报错。

对于两个数求和的代码: 

template<class T>
T  Add(T a, T b)
{return a + b;
}
int main()
{int a = 10, b = 20;double c = 10.1, d = 9.3;Add(a, d);return 0;
}

错误示例如下:

我们用了int,double两个类型的实参去调用函数模板,这是不行的。

要解决这种错误有两种方法,一种是类型强制类型转换,一种是显示实例化,告诉编译器模板参数类型。

显示实例化

显示实例化:在函数名后的<>中指明模板参数类型。

在进行函数模板的调用时,我们直接告诉编译器模板参数的类型。具体代码如下:

template<class T>
T Add(T a, T b)
{return a + b;
}
int main()
{int a = 10, b = 20;double c = 10.1, d = 9.3;Add(a, d);Add<int>(a, d);  //告诉编译器,模板参数的类型return 0;
}

类模板

我们为什么要引入类模板呢?

在我们学习栈时,我们学习栈一般是数组栈,栈的每个元素是有具体的类型的,但是如果我们想让栈的元素的类型灵活的变化,按照之前C语言的方式实现栈的话,我们可能得实现多个只有元素类型不同的栈(每次都用typedef定义不同的数据结构),会导致代码冗余,当然这只是针对相对空间较小栈,如果我们后期学习了一个相对空间很大的数据结构,如果再次碰到了这种情景,如果还是这样进行实现,就会导致大量资源的浪费,所以针对这种情况,C++的大佬们发明了类模板。我们依然以栈这个数据结构作为讲解,栈的类模板代码如下:

template<class T>
class Stack
{
public:Stack(int capacity=4):_top(0), _capacity(capacity){_a = new T[capacity];}~Stack(){delete[] _a;_a = nullptr;_capacity = _top = 0;}
private:T* _a;int _Top;int _capacity;
};int main()
{Stack<int> st1;Stack<double> st2;Stack<int*> st3;return 0;
}

注意:在之前我们类类型就是类名,但是在有了类模板之后,类类型就不再是类名了,此时也不能进行类模板的隐式实例化,只能进行类模板的显示实例化,所以此时的类类型就是类名<模板参数类型> 。此时我们创建对象不能再次使用类名创建对象,必须使用类名<模板参数类型> 创建对象

以上便是我们本期模板的所有内容,模板是学习STL的基础,小伙伴们一定要掌握模板的相关内容。

本期内容到此结束^_^

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

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

相关文章

算法训练营Day14

#Java #二叉树层次遍历 #反转二叉树 开源学习资料 二叉树的层次遍历&#xff1a;力扣题目链接 二叉树的层次遍历很好理解&#xff1a; 就是从根结点一层一层地往下遍历&#xff08;同一层&#xff0c;从左到右&#xff09;&#xff1a; 迭代的方式很好理解&#xff1a;就是…

【Axure RP9】动态面板使用------案例:包括轮播图和多方式登入及左侧菜单栏案例

目录 一 动态面板简介 1.1 动态面板是什么 二 轮播图 2.1 轮播图是什么 2.2 轮播图应用场景 2.3 制作实播图 三 多方式登入 3.1多方式登入是什么 3.3 多方式登入实现 四 左侧菜单栏 4.1左侧菜单栏是什么 4.2 左侧菜单栏实现 一 动态面板简介 1.1 动态面板是什么…

嵌入式系统挑战赛题目----简单栈数据结构

一、题目要求 实现一个简单的栈数据结构。栈是一种后进先出线性数据结构&#xff0c;只能在一端进行插入和删除操作。请编写一个C语言程序&#xff0c;实现包括栈的初始化、入栈、出栈以及判断栈是否为空等基本操作。 请根据要求在begin、end间完成代码&#xff0c;不要改变代…

高速无刷直流电机霍尔板在高速无刷直流三相电机上是一个什么样的角色

目录 一、0-30阶段 二、30-60阶段 三、60-90阶段 三相电机在各领域应用广泛&#xff0c;是现代工业和生活的重要设备。三相全波无刷电机的旋转原理可以分为0-90旋转的详细说明如下&#xff1a; 首先&#xff0c;我们以一个三相60相带的无刷直流电机为例&#xff0c;来说明其…

【Linux】进程周边004之进程的调度与切换(领略Linux系统进程调度算法的神奇)

&#x1f440;樊梓慕&#xff1a;个人主页 &#x1f3a5;个人专栏&#xff1a;《C语言》《数据结构》《蓝桥杯试题》《LeetCode刷题笔记》《实训项目》《C》《Linux》 &#x1f31d;每一个不曾起舞的日子&#xff0c;都是对生命的辜负 目录 前言 1.进程切换 2.进程调度 2.…

VBA_MF系列技术资料1-242

MF系列VBA技术资料 为了让广大学员在VBA编程中有切实可行的思路及有效的提高自己的编程技巧&#xff0c;我参考大量的资料&#xff0c;并结合自己的经验总结了这份MF系列VBA技术综合资料&#xff0c;而且开放源码&#xff08;MF04除外&#xff09;&#xff0c;其中MF01-04属于定…

【多线程】Java中多线程的几种实现方式

多线程&#xff08;multithreading&#xff09;是指在一个程序中同时执行多个不同的线程&#xff08;thread&#xff09;&#xff0c;每个线程都是程序的一部分&#xff0c;是独立的执行路径。相比于单线程程序&#xff0c;多线程程序可以更充分地利用计算机的多核心或多处理器…

PyTorch: 基于【VGG16】处理MNIST数据集的图像分类任务【准确率98.9%+】

目录 引言在Conda虚拟环境下安装pytorch步骤一&#xff1a;利用代码自动下载mnist数据集步骤二&#xff1a;搭建基于VGG16的图像分类模型步骤三&#xff1a;训练模型步骤四&#xff1a;测试模型运行结果后续模型的优化和改进建议完整代码结束语 引言 在本博客中&#xff0c;小…

对不起,必须放弃SQL!

尽管SQL很受欢迎&#xff0c;也很成功&#xff0c;但它又总是充斥着种种矛盾。 SQL可能笨拙又冗长&#xff0c;但开发人员又经常发现它往往是他们提取所需数据的最简单直接的方法。当查询写入正确时&#xff0c;它可以快如闪电&#xff0c;当查询出错时&#xff0c;它就会慢如…

elementUi表单验证 上一下两项都有必填校验,添加v-if后失效

需在el-form-item 在不一样的key区分就在页面会生效

ConnectionError怎么解决

文章目录 解决思路lz的具体解决过程 解决思路 这个错误表明在尝试加载评价指标时&#xff0c;代码试图从 huggingface 下载文件&#xff0c;但由于代理错误而无法连接。 为了解决这个问题&#xff0c;你可以尝试以下几个步骤&#xff1a; 1.设置代理&#xff1a; 如果你在使…

jmeter接口测试项目实战详解,零基础也能学

1.什么是jmeter&#xff1f; JMeter是100%完全由Java语言编写的&#xff0c;免费的开源软件&#xff0c;是非常优秀的性能测试和接口测试工具&#xff0c;支持主流协议的测试 2.jmeter能做什么&#xff1f; 1.JMeter是100%完全由Java语言编写的软件性能测试的GUI的测试工具&…