【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;
}
当然用C也可以,但是C实现的话,只能搞成不同函数名来实现不同变量的交换,而且还没有引用的语法。
但是不论是上面的函数重载还是用C来实现,都好麻烦,当我们每次想要交换新类型的交换的时候都要再重写一个函数。
也就是下面的缺点:
- 重载的函数仅仅是类型不同,代码复用率比较低,只要有新类型出现时,就需要用户自己增加对应的函数
- 代码的可维护性比较低,一个出错可能所有的重载均出错
活字印刷,相信大家都听过。

通过改变模具中的字来印刷出不同的文章。
那能否告诉编译器一个模具,让编译器根据不同的类型利用该模具来生成代码呢?
如果在C++中,也能够存在这样一个模具,通过给这个模具中填充不同文字块(类型),来获得不同文字的文章(即生成具体类型的代码)。
这就是本篇博客要讲的模板。
目录中的泛型编程是指编写与类型无关的通用代码,是代码复用的一种手段。模板是泛型编程的基础。
模板分为两类,函数模板和类模板。

函数模板
概念
函数模板代表了一个函数家族,该函数模板与类型无关,在使用时被参数化,根据实参类型产生函数的特定类型版本。
格式
//写函数前要加这个
template<typename T1, typename T2,......,typename Tn>
//typename后面的T1,这种就相当于我们定义变量时候的变量名,是
//随便取的,只不过这里是类型名。常用的还有K,V,跟T合起来就是KTV。//然后再写函数
返回值类型 函数名(参数列表){}
来个交换的例子:

下面都是OK的。

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

目前阶段,记住写成typename和class都是可以的。
再来个交换int和交换double的例子:

但是记住,上面的代码中,交换int和交换double走的不是一个函数。
函数模板的原理
大家都知道,瓦特改良蒸汽机,人类开始了工业革命,解放了生产力。机器生
产淘汰掉了很多手工产品。本质是什么,重复的工作交给了机器去完成。
函数模板是一个蓝图,它本身并不是函数,是编译器用使用方式产生特定具体类型函数的模具。所以其实模板就是将本来应该我们做的重复的事情交给了编译器。

在编译器编译阶段,对于模板函数的使用,编译器需要根据传入的实参类型来推演生成对应类型的函数以供调用。比如:当用double类型使用函数模板时,编译器通过对实参类型的推演,将T确定为double类型,然后产生一份专门处理double类型的代码,对于字符类型也是如此。
如何证明呢?
看图(稍微懂一点反汇编就行):

右侧的反汇编中,交换int和交换double的函数地址是不一样的。
其实也可以对应到活字印刷术当中,我们想要有一份文章的拷贝,不是用活字印刷里面的木头块来读的,而是通过那些木头块来把文章印到纸上来读的。
所以上面的就很好理解了,不是用模板,而是用模板来实例化出对应的函数来使用。
其实,C++标准库中也是有交换的函数的,只不过用起来是小写swap。

可以看到,标准库中实现的就是用的模板。
我们可以直接使用:

函数模板的实例化
用不同类型的参数使用函数模板时,称为函数模板的实例化。模板参数实例化分为:隐式实例化和显式实例化。
-
隐式实例化:让编译器根据实参推演模板参数的实际类型
先给个能跑的例子:编译器自动推演
再给个跑不了的例子:

出现上面问题的原因是a和d1的类型是不相同的,而模板函数中两个参数的类型是相同的,但是我们偏要生成一个int和double的函数,这样是生成不了的。因为编译器不能决定到底是用int还是用double来实现。编译器就犯难了,只能报错,不然就得背黑锅。 -
模板函数不允许自动类型转换,但普通函数可以进行自动类型转换
但是我们之前写的函数是可以进行隐式类型转换的。比如说下面这样:

如果想用模板来实现两个不同类型相加的时候,可用以下方法:

但是这样非常挫。
可以用下面的显示实例化来实现。
- 显示实例化:在函数名后的<>中指定模板参数的实际类型

这个方法在函数模板中不是那么常用,但是在类模板中就非常常用了。
再给个在函数模板中适用的场景。

上面不能直接使用func,因为模板中的T是不确定的。
这时候就要用到<>了。

当我们同时拥有模板和一个功能相同的加法函数的时候会发生什么?

会像上面这样,但是上面的写法是很挫的,不建议同时出现功能相同的函数模板。
类模板
类模板的定义格式
template<class T1, class T2, ..., class Tn>
class 类模板名
{// 类内成员定义
};
和函数模板很像。
类模板的是使用场景是什么呢?
我们来写一个简单的类模板。

如果想将类模板中的的成员函数在类外定义的话,得像这样:

还要说一点就是模板不支持分离编译。 声明放在.h 定义放在.cpp。
至于为什么的话放到后面深入讲模板的博客中说。
类模板的实例化

如果不指明T的类型,是会报错的。
那么用类模板的时候就要显示指出T的类型。

最后再给一个顺序表的例子:
直接把代码给出来:
template<typename T>
class Stack
{
public:Stack(size_t capacity = 4):_data(nullptr),_top(0),_capacity(0){if (capacity > 0){_data = new T[capacity];_top = 0;_capacity = 4;}}~Stack(){delete[] _data;_data = nullptr;_top = _capacity = 0;}void Push(const T& a){if (_capacity == _top){int newcapacity = _capacity == 0 ? 4 : 2 * _capacity;T* newdata = new T[newcapacity];if (_data){memcpy(newdata, _data, sizeof(T) * _capacity);delete[] _data;}_data = newdata;_capacity = newcapacity;}_data[_top] = a;++_top;}void Pop(){assert(_top);--_top;}bool Empty(){return _top == 0;}const T& Top(){return _data[_top - 1];}private:T* _data;size_t _top;size_t _capacity;
};int main()
{Stack<int> s;s.Push(1);s.Push(2);s.Push(3);s.Push(4);s.Push(5);while (!s.Empty()){cout << s.Top() << " ";s.Pop();}cout << endl;return 0;
}
其中最重要的是下面main函数中的Stack<int> s; 这条语句。
到此结束。。。
相关文章:
【C++】模板的一点简单介绍
模板 前言泛型编程函数模板概念格式函数模板的原理函数模板的实例化 类模板类模板的定义格式类模板的实例化 前言 这篇博客讲的是模板的一些基本知识,并没有那么深入,但是如果你是为了过期末考试而搜的这篇博客,我觉得下面讲的是够了的。 之…...
SpringCloud概述
前言 什么是微服务? 微服务是一种面向服务的架构(SOA)风格,其中,应用程序被构建为多个不同的小型服务的集合而不是单个应用程序。与单个程序不同的是,微服务让你可以同时运行多个独立的应用程序,而这些独立的应用…...
Metal入门学习:GPU并行计算大数组相加
一、编程指南PDF下载链接(中英文档) 1、Metal编程指南PDF链接 https://github.com/dennie-lee/ios_tech_record/raw/main/Metal学习PDF/Metal 编程指南.pdf 2、Metal着色语言(Metal Shader Language:简称MSL)编程指南PDF链接 https://github.com/dennie-lee/ios_te…...
关于在spyder,jupyter notebook下创建虚拟环境(pytorch,tensorflow)均有效
anaconda下载地址 https://www.anaconda.com/download/ 下载完成后打开anaconda目录下的 anaconda prompt 在命令行中输入下面的命令创建一个叫tf2.0的虚拟环境(“tf2.0”是建立的Conda虚拟环境的名字,可以自拟) conda create -n tf2.0 p…...
oracle 闪回恢复
oracle 闪回恢复 闪回恢复区主要通过3个初始化参数来设置和管理: db_recovery_file_dest:指定闪回恢复区的位置 db_recovery_file_dest_size:指定闪回恢复区的可用空间大小 db_flashback_retention_target:指定数据库可以回退的时…...
LeetCode 322 零钱兑换
题目: 给你一个整数数组 coins ,表示不同面额的硬币;以及一个整数 amount ,表示总金额。计算并返回可以凑成总金额所需的 最少的硬币个数 。如果没有任何一种硬币组合能组成总金额,返回 -1 。你可以认为每种硬币的数量…...
面试篇SpringMVC是什么以及工作原理
1,什么是SpringMVC呢? 它是Spring的一种设计模式,一款框架。 2,MVC分别代表什么? M代表模型即model的缩写,指业务逻辑层模型。V代表视图即View的缩写,指视图层。C则是controller的缩写ÿ…...
jQuery-层级选择器
<!DOCTYPE HTML> <html> <head> <meta http-equiv"Content-Type" content"text/html; charsetUTF-8"> <title>层级选择器</title> <style type"text/css"> …...
【Java数据结构】——第十节(下).选择排序与堆排序
作者简介:大家好,我是未央; 博客首页:未央.303 系列专栏:Java初阶数据结构 每日一句:人的一生,可以有所作为的时机只有一次,那就是现在!!! 文章目…...
45道SQL题目陆续更新
文章目录 学习视频配置环境第一天内连接 外连接第二天第三天 学习视频 学习视频 配置环境 四张表 配置四张表的sql语句 #创建发据库 create database frogdata charsetutf8;use frogdata;# 学生表 Student create table Student( SId varchar(10), Sname var…...
在线PS软件有哪些不错的推荐
许多新的UI设计合作伙伴非常关心在线ps工具的选择。现在市场上有各种各样的ps网页替代工具,数量众多,令人眼花缭乱。本文简要介绍了10个在线PS工具,我相信一定有一个适合你! 1.即时设计 即时设计是一款在线 UI 设计工具…...
Java实现天气预报功能
如果要实现类似百度天气、手机App这样的天气预报功能该如何实现?首先想到的是百度... 背景: 最近公司做了一个项目,天气预报的功能也做上去了,不仅有实时天气、未来7天预报的功能、还有气象预警的功能。 天气包括基本天气、白天夜…...
python循环语句
while循环 Python中,while循环只要在条件(表达式)为真的情况下,就会一直重复执行相应的循环代码块。 while语句的语法格式如下: while 条件表达式:代码块while语句执行的具体流程为:首先判断…...
多线程基础(一)线程基础信息、synchronized 锁概念
1. 基本概念: 程序: 程序是一些保存在磁盘上的指令的有序集合,是静态的。程序包括:内存资源、IO资源、信号处理等。(如:XX.exe) 进程: 进程是程序执行的过程,包括了动态…...
JAVA期末考内容知识点的梳理
作者的话 前言:这些都是很基本的,还有很多没有写出来,重点在于考试复习,包括后四章的内容 前面内容请参考JAVA阶段考内容知识点的梳理 一、集合、流 课堂总结1集合 集合概念: 保存和盛装数据的容器,将许多…...
为什么要使用Thrift与Protocol Buffers?
编码数据的格式 程序通常(至少)使用两种形式的数据: 在内存中,数据保存在对象、结构体、列表、数组、散列表、树等中。 这些数据结构针对 CPU 的高效访问和操作进行了优化(通常使用指针)。如果要将数据写…...
oa是什么意思?oa系统哪个好用?
一、oa是什么意思 oa(Office Automation办公自动化)是一种将智能化科技应用于企业管理中的应用系统。它可以通过电脑网络、互联网等技术手段,将企业的各种业务流程、各种业务数据进行集成和处理,将各种业务流程和各种业务数据统一…...
Linq和C# Lambda表达式
什么是Linq 简介 Linq (Language Integrated Query) 是一种语言集成的查询技术,可以在C#和其他.NET语言中使用。Linq允许我们使用一种类SQL的语言来查询数据,这使得代码更加简洁和易于阅读。Linq提供了一种通用的查询接口,可以用于查询各种…...
蓝桥:前端开发笔面必刷题——Day2 数组(三)
文章目录 📋前言🎯两数之和 II📚题目内容✅解答 🎯移除元素📚题目内容✅解答 🎯有序数组的平方📚题目内容✅解答 🎯三数之和📚题目内容✅解答 📝最后 &#x…...
人工智能专栏第四讲——人工智能的未来展望与机遇
目录 一、人工智能的未来展望 二、人工智能在各领域的应用 三、人工智能的机遇 四、总结...
JVM垃圾回收机制全解析
Java虚拟机(JVM)中的垃圾收集器(Garbage Collector,简称GC)是用于自动管理内存的机制。它负责识别和清除不再被程序使用的对象,从而释放内存空间,避免内存泄漏和内存溢出等问题。垃圾收集器在Ja…...
linux 下常用变更-8
1、删除普通用户 查询用户初始UID和GIDls -l /home/ ###家目录中查看UID cat /etc/group ###此文件查看GID删除用户1.编辑文件 /etc/passwd 找到对应的行,YW343:x:0:0::/home/YW343:/bin/bash 2.将标红的位置修改为用户对应初始UID和GID: YW3…...
三体问题详解
从物理学角度,三体问题之所以不稳定,是因为三个天体在万有引力作用下相互作用,形成一个非线性耦合系统。我们可以从牛顿经典力学出发,列出具体的运动方程,并说明为何这个系统本质上是混沌的,无法得到一般解…...
GC1808高性能24位立体声音频ADC芯片解析
1. 芯片概述 GC1808是一款24位立体声音频模数转换器(ADC),支持8kHz~96kHz采样率,集成Δ-Σ调制器、数字抗混叠滤波器和高通滤波器,适用于高保真音频采集场景。 2. 核心特性 高精度:24位分辨率,…...
零基础在实践中学习网络安全-皮卡丘靶场(第九期-Unsafe Fileupload模块)(yakit方式)
本期内容并不是很难,相信大家会学的很愉快,当然对于有后端基础的朋友来说,本期内容更加容易了解,当然没有基础的也别担心,本期内容会详细解释有关内容 本期用到的软件:yakit(因为经过之前好多期…...
return this;返回的是谁
一个审批系统的示例来演示责任链模式的实现。假设公司需要处理不同金额的采购申请,不同级别的经理有不同的审批权限: // 抽象处理者:审批者 abstract class Approver {protected Approver successor; // 下一个处理者// 设置下一个处理者pub…...
Linux中《基础IO》详细介绍
目录 理解"文件"狭义理解广义理解文件操作的归类认知系统角度文件类别 回顾C文件接口打开文件写文件读文件稍作修改,实现简单cat命令 输出信息到显示器,你有哪些方法stdin & stdout & stderr打开文件的方式 系统⽂件I/O⼀种传递标志位…...
【Kafka】Kafka从入门到实战:构建高吞吐量分布式消息系统
Kafka从入门到实战:构建高吞吐量分布式消息系统 一、Kafka概述 Apache Kafka是一个分布式流处理平台,最初由LinkedIn开发,后成为Apache顶级项目。它被设计用于高吞吐量、低延迟的消息处理,能够处理来自多个生产者的海量数据,并将这些数据实时传递给消费者。 Kafka核心特…...
高抗扰度汽车光耦合器的特性
晶台光电推出的125℃光耦合器系列产品(包括KL357NU、KL3H7U和KL817U),专为高温环境下的汽车应用设计,具备以下核心优势和技术特点: 一、技术特性分析 高温稳定性 采用先进的LED技术和优化的IC设计,确保在…...
LINUX编译vlc
下载 VideoLAN / VLC GitLab 选择最新的发布版本 准备 sudo apt install -y xcb bison sudo apt install -y autopoint sudo apt install -y autoconf automake libtool编译ffmpeg LINUX FFMPEG编译汇总(最简化)_底部的附件列表中】: ffmpeg - lzip…...
