【C++笔记】模板初阶

前言

各位读者朋友们大家好,上期我们讲完了C++的内存管理部分,这一期我们开始初步认识一下模板。

目录

  • 前言
  • 一. 泛型编程
  • 二. 函数模板
    • 2.1 函数模板概念
    • 2.2 函数模板的格式
    • 2.3 函数模板的原理
    • 2.4 函数模板的实例化
    • 2.5 模板函数匹配规则
  • 三. 类模板
    • 3.1 类模板的格式
    • 3.2 类模板的实例化
    • 3.3 类模板的成员函数定义和声明分离
  • 结语

一. 泛型编程

如何实现一个交换函数呢?

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;
}

通过函数重载可以实现,但是函数重载有很多弊端:
1.重载的函数只是类型不同,代码的复用率较低,只要有新类型出现时,就需要用户自己增加对象的函数。
2.代码的可维护性较低,一个出错可能所有的重载都出错。
我们发现,交换函数里面的逻辑是一样的,只是参数不一样,每次都这样写是不是有点冗余,那能否告诉编译器一个模子,让编译器根据不同的类型利用该模子来生成代码呢?

在这里插入图片描述
如果在C++中,也能够存在这样一个模具,通过给这个模具中填充不同材料(类型),来获得不同材料的食品(即生成具体类型的代码),那将会节省许多头发。巧的是前人早已将树栽好,我们只需在此乘凉。
泛型编程:编写与类型无关的普通代码,是代码复用的一种手段。模板是泛型编程的基础。
在这里插入图片描述

二. 函数模板

2.1 函数模板概念

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

2.2 函数模板的格式

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

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

注意:typename是用来定义模板参数关键字,也可以使用class(切记:不能使用struct代替class)
在这里插入图片描述
虽然两者都是Swap函数,同一个模板,但调用的却不是同一个函数,生成的函数是编译器帮我们生成的。而且上面的Swap函数的参数的类型必须保持一致,因为模板中的参数类型是根据实参推测出来的,如果给x整型,y为double类型,编译就会报错。对于不同类型的参数我们可以写成下面的写法,给模板多参数类型:

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

2.3 函数模板的原理

函数模板是一个蓝图,它本身并不是函数,是编译器用使用方式产生特定类型函数的模具。模板就是将本来应该由我们做的事情交给了编译器。
在这里插入图片描述
在编译器编译阶段,对于模板函数的使用,编译器需要根据传入的实参来推测生成对以哦那个类型的函数以供使用。比如:当用double类型使用函数模板时,编译器通过对实参类型的推测,将T确定为double类型,然后产生一份专门处理double类型的函数。在使用模板函数的时候一定要声明变量的类型。

2.4 函数模板的实例化

用不同类型的参数使用函数模板时,称为函数模板的实例化。模板实例化分为:隐式实例化和显式实例化。

  • 1. 隐式实例化:让编译器根据实参的类型推演出模板参数的类型。
template <typename T>
T& Add(const T& x, const T& y)
{
	return x + y;
}
int main()
{
	int a = 520, b = 1314;
	double m = 520.52, n = 1314.14;
	cout << Add(a, b) << endl;
	cout << Add(m, n) << endl;
	return 0;
}

如果想求两个不同类型参数的和可以走强制类型转换:
在这里插入图片描述
也可以走模板的实例化:用函数的模板生成相应的函数

  • 2.显式实例化:在函数名后的<>中指定模板参数的实际类型
    在这里插入图片描述
    在这里插入图片描述
    如果类型不匹配,编译器会尝试进行隐式类型转换,如果无法转换成功编译器将会报错。
    在这里插入图片描述
    像这种没有传模板类型的函数模板,在调用时就一定要显式实例化。

2.5 模板函数匹配规则

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

template <typename T>
T Add(const T& x, const T& y)
{
	return x + y;
}
int Add(const int& x, const int& y)
{
	return (x + y)*10;
}

int main()
{
	int m = 520, n = 1314;
	cout << Add(m, n);
	return 0;
}

在这里插入图片描述
这种话情况下优先调用非模板函数。

  • 2. 对于非模板函数和同名模板函数,如果其他条件都相同,在调用时会优先调用非模板函数而不会从该模板产生出一个实例。如果模板可以产生一个更好匹配的函数,那么就选择模板函数。
    在这里插入图片描述
    第二次调用Add函数,模板可以产生更匹配的,因此使用模板。

三. 类模板

3.1 类模板的格式

template<class T1, class T2, ..., class Tn> 
class 类模板名
{
 // 类内成员定义
}; 
template <typename T>
class Stack
{
public:
	Stack(int n = 4)
		:_array(new T[n])
		,_size(0)
		,_capacity(n)
	{}
	~Stack()
	{
		delete[] _array;
		_array = nullptr;
		_size = _capacity = 0;
	}
	void Push(const T& x)
	{
		if (_size == _capacity)
		{
			T* tmp = new T[_capacity * 2];
			memcpy(tmp, _array, sizeof(Stack) * _size);
			delete[] _array;
			_array = tmp;
			_capacity *= 2;
		}
		_array[size++] = x;
	}
private:
	T* _array;
	size_t _size;
	size_t _capacity;
};

类模板和用typedef数据类型的类在于类模板可以同时产生多种不同类型的类,而用typedef不行。

3.2 类模板的实例化

类模板实例化与函数模板实例化不同,类模板实例化需要在类模板名字后跟<>,然后将实例化的类型放在<>中即可,类模板名字不是真正的类,而实例化的结果才是真正的类。
在这里插入图片描述
在调用类模板的时候必须显示实例化

3.3 类模板的成员函数定义和声明分离

在这里插入图片描述
声明和定义分离要重新定义模板参数,而且定义和声明不能放到两个文件中。
在这里插入图片描述

结语

以上就是关于模板初阶内容的详尽讲解,衷心感谢每一位读者的耐心阅读。希望通过这些内容,能够为大家在学习和使用模板的过程中提供有价值的启示和帮助。模板作为C++中强大的特性之一,其初阶知识的掌握对于后续深入学习和应用至关重要。非常期待大家能够从中受益,并在实际编程中灵活运用。同时,也诚挚地欢迎大家提出宝贵的批评和建议,您的反馈将是我不断进步的动力。再次感谢大家的支持与关注!

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

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

相关文章

vue3组件通信--props

目录 1.父传子2.子传父 最近在做项目的过程中发现&#xff0c;props父子通信忘的差不多了。下面写个笔记复习一下。 1.父传子 父组件&#xff08;FatherComponent.vue&#xff09;&#xff1a; <script setup> import ChildComponent from "/components/ChildComp…

海外媒体发稿:如何打造媒体发稿策略

新闻媒体的发稿推广策略对于提升品牌知名度、吸引流量以及增加收入非常重要。本文将介绍一套在21天内打造爆款新闻媒体发稿推广策略的方法。 第一天至第七天&#xff1a;明确目标和定位 在这个阶段&#xff0c;你需要明确你的目标和定位&#xff0c;以便为你的新闻媒体建立一个…

1U服务器和Hyper-V虚拟机使用记录

记录最近接触服务器和虚拟机的一些使用操作知识 背景&#xff1a;1U服务器上架使用&#xff0c;备份其他服务器vm虚拟机&#xff0c;Hyper-V管理虚拟机使用测试 设备&#xff1a;IBM3550服务器交换机&#xff0c; 移动硬盘&#xff1a;附加存储盘&#xff0c; u盘1&#xff1…

GCN+BiLSTM多特征输入时间序列预测(Pytorch)

目录 效果一览基本介绍程序设计参考资料 效果一览 基本介绍 GCNBiLSTM多特征输入时间序列预测&#xff08;Pytorch&#xff09; 可以做风电预测&#xff0c;光伏预测&#xff0c;寿命预测&#xff0c;浓度预测等。 Python代码&#xff0c;基于Pytorch编写 1.多特征输入单步预测…

sersync实时同步部署案例

目录 sersync介绍 案例信息 操作步骤 服务端部署 客户端部署 创建存储目录 安装sersync 修改配置文件 启动服务 停止服务 测试 sersync介绍 sersync是一个基于inotifyrsync的实时文件同步工具&#xff0c;通过监控目录的变动达到实时同步的目的。 案例信息 拓扑…

ELK之路第一步——Elasticsearch集群的搭建以及踩坑记录

elasticSearch集群 前言一、架构二、下载三、虚拟机相关设置3.1 创建es用户3.2 为建es用户赋权sudo3.3 更换es目录所属用户 四、Elasticsearch配置文件修改4.1 修改elasticsearch.yml4.2 修改jvm.options4.3 修改jdk路径 五、启动六、启动报错七、可视化界面cerebro 前言 Elk&…

SwiftUI:单个App支持设置多语言

SwiftUI 全新多语言方案 简化本地化的字符串- WWDC21 - 视频 本地化您的SwiftUI app - WWDC21 - 视频 构建全球化App&#xff1a;本地化的示例- WWDC22 - 视频 构建支持多语言的App - WWDC24 - 视频 单个App支持设置多语言 工程 Info.plist里添加 键值UIPrefersShowingLangua…

go 使用fyne实现桌面程序的计算器例子

使用Fyne工具包构建跨平台应用是非常简单的&#xff0c;在此之前我们需要做一些准备功能做&#xff0c;比如安装一些gcc基础图形依赖库&#xff0c;还有go语言本身的运行开发环境都是必要的。 在此之前我们希望你是go语言的已入门用户&#xff0c;掌握go的协程&#xff0c;管道…

【C++进阶篇】——STL的简介

【C进阶篇】——STL的简介 1.什么是STL STL(standard template libaray-标准模板库)&#xff1a;是C标准库的重要组成部分&#xff0c;不仅是一个可复用的组件库&#xff0c;而且是一个包罗数据结构与算法的软件框架。 2.STL的版本 原始版本 Alexander Stepanov、Meng Lee 在…

【Linux系统】环境变量

一、通俗例子解释环境变量概念与作用 想象你在厨房做饭&#xff0c;需要找到各种调料和工具。这些调料和工具就相当于计算机中的“资源”&#xff0c;而环境变量就像厨房里的一本规则书&#xff0c;里面列出了厨房里所有调料和工具的位置。 具有全局性&#xff08;所有人都能用…

MCU SCT文件学习

硬件&#xff1a;GD32F427, 外设&#xff1a;FreeRtos,ADC,DMA 现象&#xff1a;注释掉一些线程&#xff0c;发现ADC采样的线程采样不到数据了。 开始猜测是线程重入&#xff0c;破坏了地址&#xff0c;后来思考一下发现不对&#xff0c;因为注释掉线程&#xff0c;ADCDMA采…

【Vulnhub靶场】DC-4

DC-4靶场下载地址https://www.five86.com/downloads/DC-4.zip 本机IP&#xff1a;192.168.118.128 靶机IP&#xff1a;192.168.118.0/24 信息收集 扫描主机存活&#xff0c;扫描端口&#xff0c;扫描服务 第一步扫描出主机ip为192.168.118.141 nmap -sP 192.168.118.0/24 nm…

高级 SQL 技巧全面教程:提升你的数据库操作能力

高级 SQL 技巧全面教程&#xff1a;提升你的数据库操作能力 引言 在数据驱动的时代&#xff0c;SQL&#xff08;结构化查询语言&#xff09;是与数据库交互的核心工具。虽然基础 SQL 语法足以满足日常需求&#xff0c;但掌握一些高级技巧能够显著提高你的工作效率和数据处理能…

Node.js初学者指南:搭建HTTP服务器、获取请求信息及响应、变量声明与NPM包管理

精神畅快&#xff0c;心气平和&#xff1b;饮食有节&#xff0c;寒暖当心&#xff1b;起居以时&#xff0c;劳逸均匀 文章目录 node.js使用http搭建服务器的问题获取请求相关的信息响应相关的信息var、let、const对比npm使用全局安装包 node.js 概念 node.js是一个基于Chrome …

RTE 2024 隐藏攻略

大家好&#xff01;想必今年 RTE 大会议程大家都了解得差不多了&#xff0c;这将是一场实时互动和多模态 AI builder 的年度大聚会。 大会开始前&#xff0c;我们邀请了参与大会策划的 RTE 开发者社区和超音速计划的成员们&#xff0c;分享了不同活动的亮点和隐藏攻略。 请收…

使用Poste搭建内网邮件服务器

使用Poste搭建内网邮件服务器 Poste.io 也是一个流行的邮件服务器方案&#xff0c;它可以通过 Docker 容器轻松部署&#xff0c;非常适合搭建内部邮件服务器。 本文档将向您展示如何开始使用 Poste.io 邮件服务器。在 5 分钟内&#xff0c;您将拥有一个可发送和接收邮件的邮件…

WSL2 Ubuntu22.04编译安装LLVM

前提 这两天因为工作需要&#xff0c;要编译一个Debug版本的llvm。这里对编译安装过程进行一个简单的记录&#xff0c;同时也记录下这个过程中遇到的几个问题。 下载源码并编译 有关llvm编译安装的官方文档在这里。 从git仓库clone llvm的源码。 git clone https://github.c…

SD-WAN企业组网的应用场景

SD-WAN&#xff08;软件定义广域网&#xff09;能够实现企业不同站点之间的高效互联&#xff0c;确保分支机构、总部、数据中心以及云平台等站点的顺畅通信。本文将探讨从企业的WAN业务需求出发&#xff0c;可以将SD-WAN的组网场景分为哪几类。 SD-WAN的典型组网场景 企业站点之…

Docker中如何控制服务启动顺序实现探讨

文章目录 一、Docker概述二、Docker三剑客1. Compose2. Machine3. Swarm 三、简要需求1. 样例工程2. 代码模块3. 调用方向4. 期望启动顺序 四、思路分析1.各走各路1.&#xff09;docker-compose -f指定不同配置文件2.&#xff09;docker-compose up -d service-name指定服务名3…

基于SpringBoot的高校体测管理系统设计与实现(源码+定制+开发)高校体测记录系统设计、高校体测信息管理平台、智能体测管理系统开发、高校体测记录系统设计

博主介绍&#xff1a; ✌我是阿龙&#xff0c;一名专注于Java技术领域的程序员&#xff0c;全网拥有10W粉丝。作为CSDN特邀作者、博客专家、新星计划导师&#xff0c;我在计算机毕业设计开发方面积累了丰富的经验。同时&#xff0c;我也是掘金、华为云、阿里云、InfoQ等平台…