template—模板初阶(C++)

        本篇将会对 Cpp 中的模板进行一个简单的介绍(后序还关系模板进阶,对模板的内容进行更深入的讲解),其中包括模板的使用:函数模板、类模板,以及对于泛型编程的理解。其中的重点为函数模板,介绍了函数模板的原理、隐式实例化和显示实例化、还有模板参数的匹配规则。目录如下:

目录

1. 泛型编程

2. 函数模板

2.1 函数模板的格式

2.2 函数模板原理

2.3 函数模板的实例化

2.4 模板参数的匹配规则

3. 类模板

1. 泛型编程

        通常我们在实现一个 Swap 函数的时候,对于不同参数类型的 Swap 函数,我们需要写很多个重载函数来解决这个 Swap 函数的问题,但是当我们遇到一个新的形参类型的时候,我们有需要重新写一个新的重载函数,那么我们有没有其他的办法来解决该问题呢?

        我们可以使用模板,只提供一个函数,就可以以上问题,不在需要写很多的重载函数。模板的出现,开辟了泛型编程的道路 ---> 也就为之后的 STL 打下了基础。

        泛型编程:编写与类型无关的通用代码,是代码复用的一种手段。(模板是泛型编程的基础)

        如下:

// 函数重载的 Swap 函数
void Swap(double& x, double& y) {
	double tmp = x;
	x = y;
	y = tmp;
}

void Swap(int& x, int& y) {
	int tmp = x;
	x = y;
	y = tmp;
}

void Swap(char& x, char& y) {
	char tmp = x;
	x = y;
	y = tmp;
}

// Swap 的模板代码
template <typename T>
void Swap(T& x, T& y) {
	T tmp = x;
	x = y;
	y = tmp;
}

2. 函数模板

        对于函数模板的使用,存在很多的细节,将会在下面较为详细的列举。

        首先是对于函数模板的概念:函数模板代表了一个函数家族,在使用时被参数化,根据实参类型产生函数的特定类型版本

2.1 函数模板的格式

        函数模板格式如下:

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

        注:typename 是用来定义模板参数的关键字,也可以使用 class ,但不能使用 struct 作为定义模板参数的关键字。

        样例如下:

template <typename T1, typename T2>
void Swap(T1& x, T2& y) {
	T1 tmp = x;
	x = y;
	y = tmp;
}

2.2 函数模板原理

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

        在编译器编译阶段,对于模板函数的使用,编译器根据传入的实参类型来推演生成对应类型的函数以提供调用,如:当使用 double 类型使用函数模板时,编译器通过对实参类型的推演,将 T 确定为 double 类型,然后产生一份专门处理 double 类型的代码,对于内置类型同样如此。如下的反汇编:

        如上,我们在汇编层面可以看见,执行到需要运行的函数时,函数模板会自动的推演函数参数类型。推理过程如下:

2.3 函数模板的实例化

        当我们使用不同类型的参数使用函数模板的时候,称为函数模板的实例化。模板参数实例化分为:隐式实例化和显示实例化,如下:

        对于模板参数而言,只存在一个 T,而这个时候,我们将 int 类型的 a1 和 double 类型的 d2 传入到函数之中去,函数模板无法推断我们需要使用的函数是 int 类型的还是 double 类型,所以编译器会报错。解决以上问题一共有两种办法,分别是隐式转化和显示转化,如下:

        如上,红框圈住的为隐式实例化:隐式实例化让编译器根据实参推演模板参数的实际类型,我们可以在传入的参数中将其强转,已到达实参的类型相同。

        蓝框圈住的为显式实例化:显式实例化在函数名后的 <> 中指定模板参数的实际类型,这样可以将传入的所有类型都转换为 <> 中的类型。

        注:对于显示实例化和隐式实例化而言,当函数中确实存在类型的强转:在强转的时候会产生一个临时变量,而对于该临时变量而言是一个不可以修改的值,所以我们需要使用 const 对其进行修饰,若不使用 const 对其进行修饰,那么就会报错,所以说,这样的显式实例化和隐式实例化就不能用在 Swap 函数中,因为 Swap 函数中的参数需要交换,为需要改变的值,其中产生的临时变量与其函数参数不匹配,就会报错。

2.4 模板参数的匹配规则

        对于模板参数的匹配存在以下原则:

        1. 一个非模板函数可以和一个同名的函数模板同时存在,而且函数模板也可以被实例化为这个非模板函数,如下:

        当调用的函数与非模板函数匹配的时候,编译器不要使用模板进行特化,直接调用存在的函数,但是我们也可以调用模板函数,只需要在函数名后的 <> 添加对应的类型即可,就算已经存在对应的函数,我们仍然可以调用其模板函数。

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

        简单来说,会优先匹配已经存在的非模板函数,若没有,则在匹配模板函数。

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

3. 类模板

        对于类模板而言,类模板的定义格式如下:

template<typename T1, typename T2, ..., typename Tn>
class classname{
    // 类成员定义
};

        如一个栈模板:

template <class T>
class Stack {
public:
	Stack(int capacity = 4)
		:_a(new T[capacity])
		, _size(0)
		,_capacity(capacity)
	{}
	~Stack();

	void Push(T x){}
	void Pop() {}
	T GetTop(){}
private:
	T* _a;
	int _size;
	int _capacity;
};

// 当模板中函数放在类外定义时,需要加模板参数列表
template <class T>
Stack<T>::~Stack() {
	delete[] _a;
	_size = 0;
	_capacity = 0;
	_a = nullptr;
}

int main() {
	Stack<int> s1;
	Stack<double> s2;
	return 0;
}
wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

        对于以上的类模板的使用,我们可以发现,类模板更便于我们使用不同自定义类型的类,如我们可以定义出 double 类型的 stack,也可以定义出 int 类型的 stack。当我们需要在类外对类函数进行定义的时候,我们需要按照一定的形式。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

使用Docker部署jar包

vi DockerfileDockerfile内容 FROM java:8 ADD chery5G-admin.jar chery5G-admin.jar ENTRYPOINT ["java","-jar","chery5G-admin.jar"]上传jar包到Dockerfile文件同级目录 使用Dockerfile文件&#xff0c;将jar包制作为镜像 docker build -t…

04矩阵键盘实现计算器操作

需求:矩阵键盘实现计算器操作 main.c 代码如下: #include <STC89C5XRC.H> #include "ApplicationProgram.h" #include "Int_DigitalTube.h" #include "Int_MatrixKeyboard.h"void main() {u8 KeyPress;App_Initialize();while (1) {Ke…

外贸企业版本自适应通用型外贸英文多语言网站

外贸网站模板&#xff1a;自适应通用型大气外贸英文多语言网站主要是以文字内容为主导&#xff0c;将页面的设计杂乱的图片和元素进行最小化或者去除&#xff0c;从而使整个页面更加简洁、清晰&#xff0c;突出信息的呈现。 下面介绍一下外贸网站模板: 自适应通用型大气外贸英…

第46期 | GPTSecurity周报

GPTSecurity是一个涵盖了前沿学术研究和实践经验分享的社区&#xff0c;集成了生成预训练Transformer&#xff08;GPT&#xff09;、人工智能生成内容&#xff08;AIGC&#xff09;以及大语言模型&#xff08;LLM&#xff09;等安全领域应用的知识。在这里&#xff0c;您可以找…

如何使用群晖Synology Drive结合cpolar内网穿透实现同步Obsidian笔记文件

文章目录 一、简介软件特色演示&#xff1a; 二、使用免费群晖虚拟机搭建群晖Synology Drive服务&#xff0c;实现局域网同步1 安装并设置Synology Drive套件2 局域网内同步文件测试 三、内网穿透群晖Synology Drive&#xff0c;实现异地多端同步Windows 安装 Cpolar步骤&#…

无人机倾斜摄影技术在智慧城市中的应用

随着智慧城市的不断发展和完善&#xff0c;新兴热门技术也不断崛起。无人机技术作为其中之一&#xff0c;具有操作简单、应用灵活等优势&#xff0c;受到了各个行业的青睐。现阶段&#xff0c;无人机技术与5G移动通信系统、人工智能系统深度融合&#xff0c;实现了无人机技术的…

启明智显M系列--工业级HMI芯片选型表

本章主要介绍启明智显M系列HMI主控芯片&#xff1a; 纯国产自主&#xff0c; RISC-V 内核&#xff0c;配备强大的 2D 图形加速处理器、PNG/JPEG 解码引擎、H.264解码&#xff1b;工业宽温&#xff0c;提供全开源SDK&#xff1b;1秒快速开机启动的特性&#xff0c;极大地提高了…

数据结构——双向循环链表

目录 前言 一、链表的分类 二、双向循环链表 2.1 开辟新的节点 2.2 链表初始化 2.3 打印链表 2.4 链表的尾插 2.5 链表的头插 2.6 链表的尾删 2.7 链表的头删 2.8 查找链表 2.9 在pos位置之后插入数据 2.10 删除pos位置的数据 三、完整代码实现 四、顺序表和双向…

使用 R.swift(生成不了R.generated.swift)

今天算是正儿八经创建第一个swift工程&#xff0c;照着视频引用R.swift pod R.swift 工程配置 "$PODS_ROOT/R.swift/rswift" generate "$SRCROOT/R.generated.swift" $TEMP_DIR/rswift-lastrun $SRCROOT/R.generated.swift * 注意 Run角本要放在 Che…

半导体的主要四大应用

半导体是现代信息社会的基石&#xff0c;是现代工业的“粮食”&#xff0c;是电子设备产品生产制造的核心&#xff0c;它与我们的生活紧密相关。涉及到方方面面&#xff0c;半导体芯片、智能汽车、智慧电网、5G通信、航空航天、国防军工、医疗卫生等等。半导体的主要应用都有哪…

大型语言模型如何助力推荐系统:综述研究

论文地址&#xff1a;https://arxiv.org/pdf/2306.05817.pdf 这篇论文主要探讨了推荐系统&#xff08;RS&#xff09;如何从大型语言模型&#xff08;LLM&#xff09;中获益。论文首先指出&#xff0c;随着在线服务和网络应用的快速发展&#xff0c;推荐系统已成为缓解信息过载…

药店药品进销存管理系统软件可以对有效期管理查询以及对批号库存管理

药店药品进销存管理系统软件可以对有效期管理查询以及对批号库存管理 一、前言 以下软件操作教程以&#xff0c;佳易王药店药品进销存管理软件为例说明 软件文件下载可以点击最下方官网卡片——软件下载——试用版软件下载 软件可以对药品有效期进行管理查询&#xff0c;可以…

Python构建复杂数据管道库之luigi使用详解

概要 在大数据时代,处理海量数据已经成为许多应用和业务的基本需求。为了有效地管理和处理这些数据,需要强大的工具来构建可靠的数据管道。Python Luigi 就是这样一种工具,它提供了一个简单而强大的框架,用于构建复杂的数据处理流程。本文将深入探讨 Python Luigi 的核心概…

使用yolov8实现自动车牌识别(教程+代码)

该项目利用了一个被标记为“YOLOv8”的目标检测模型&#xff0c;专门针对车牌识别任务进行训练和优化。整个系统通常分为以下几个核心步骤&#xff1a; 数据准备&#xff1a; 收集包含车牌的大量图片&#xff0c;并精确地标记车牌的位置和文本信息。数据集可能包含各种环境下的…

基于java+springboot+vue实现的旅游管理系统(文末源码+Lw)23-234

摘 要 如今社会上各行各业&#xff0c;都喜欢用自己行业的专属软件工作&#xff0c;互联网发展到这个时候&#xff0c;人们已经发现离不开了互联网。新技术的产生&#xff0c;往往能解决一些老技术的弊端问题。因为传统旅游管理系统信息管理难度大&#xff0c;容错率低&#…

设计模式之解释器模式(上)

解释器模式 1&#xff09;概述 1.定义 定义一个语言的文法&#xff0c;并且建立一个解释器来解释该语言中的句子&#xff0c;这里的“语言”是指使用规定格式和语法的代码。 2.结构图 3.角色 AbstractExpression&#xff08;抽象表达式&#xff09;&#xff1a;在抽象表达…

PQMII-T20-C-A的控制功能

PQMII-T20-C-A 是一款电力质量监测仪器&#xff0c;它能够提供三相系统的连续监控。 以下是关于PQMII-T20-C-A的一些详细信息&#xff1a; 多参数测量&#xff1a;该设备具备测量电流、电压、有功功率、无功功率、能源使用、电力成本、功率因数和频率等关键电力参数的能力。波…

阿里云2024年优惠券获取方法及使用教程详解

阿里云是阿里巴巴集团旗下的云计算服务提供商&#xff0c;是全球领先的云计算及人工智能科技公司之一。提供免费试用、云服务器、云数据库、云安全、云企业应用等云计算服务&#xff0c;以及大数据、人工智能服务、精准定制基于场景的行业解决方案。 阿里云2024年优惠券的获取方…

jeecg-boot 3.6使用微服务启动详细配置

1&#xff1a;运行sql文件 2&#xff1a;配置host 路径如下 127.0.0.1 jeecg-boot-redis 127.0.0.1 jeecg-boot-mysql 127.0.0.1 jeecg-boot-nacos 127.0.0.1 jeecg-boot-gateway 127.0.0.1 jeecg-boot-system 127.0.0.1 jeecg-boot-xxljob 127.0.0.1 jeecg-boot-rabbitmq 3…