模版初阶(更新)

news2025/2/23 3:49:27

文章目录

  • 模版介绍
  • 函数模版
  • 模版匹配规则
  • 类模版
  • 结言

模版介绍

函数模版分为两个类型:

  1. 函数模版
  2. 类模版

函数模版

语法格式: t e m p l a t e < t y p n a m e T 1 , t y p n a m e T 2... > template<typname T1,typname T2...> template<typnameT1,typnameT2...>

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

int main()
{
    int a = 1, b = 2;

    double c = 1.1, d = 2.2;

    cout << a << " " << b << endl;
    swap(a, b);
    cout << a << " " << b << endl;
    
    cout << "----------------" << endl;
    
    cout << c << " " << d << endl;
    swap(c, d);
    cout << c << " " << d << endl;

    return 0;
}

在C语言中,如果我们需要分别交换 i n t int int d o u b l e double double 的数据,那么我们需要定义两个swap函数并且还不能重名。(C语言并不支持函数重载)。

而在C嘎嘎中:

在这里插入图片描述
我们只需要写一个模版就可以了。这里的T在编译的时候会默认替换为我们的 i n t int int d o u b l e double double

在这里插入图片描述
同时通过调试发现,这两个swap都进入我们写的函数模版,那么这两个Swap调用的是同一个函数吗?
在这里插入图片描述
通过反汇编发现,此时我们两个调用的并不是同一个函数。

在这里插入图片描述
当我们使用我们的 S w a p ( ) Swap() Swap()模版的时候,编译器会去默认推演我们此时的参数类型,然后编译器自动生成一个 S w a p ( ) Swap() Swap()函数,中国有句古话:死道友不死贫道[doeg]。咱们只管写一个模版,其他的交给编译器。

在这里插入图片描述
但是如果我们只有一个模版参数的话,传入两个不同类型编译器推导不出来。

此时我们有以下几种方法:
在这里插入图片描述

  1. 添加模版参数
  2. 进行强制类型转化
  3. 直接给定模版参数类型,不让编译器推演

A d d < i n t > Add<int> Add<int> 这个叫做显式实例化。它指定了参数的类型,编译器就不会推演了,T默认会 i n t int int 类型。

模版匹配规则

在这里插入图片描述
在这里插入图片描述

如上图:当我们调用 A d d ( a , b ) Add(a,b) Add(a,b) 的时候,我们写的单参数模版函数其实可以实现的,但是编译器回去默认调用最匹配的 i n t A d d ( i n t l e f t , i n t r i g h t ) int Add(int left, int right) intAdd(intleft,intright)

而当我们调用 A d d ( a , c ) Add(a,c) Add(a,c) 的时候不同参数类型我们的单参数模版函数就不行了,第一张图中我们定义了两个参数的模版参数,所以编译器会去调用我们定义的这个模版函数,而在第二张图中,编译器由于没得选了,只能被迫去调用
i n t A d d ( i n t l e f t , i n t r i g h t ) int Add(int left, int right) intAdd(intleft,intright),只不过会有 精度的丢失。

总结一下:

  • 函数调用会优先调用 (参数匹配+口味好)例如: A d d ( a , b ) Add(a,b) Add(a,b)调用 i n t A d d ( i n t l e f t , i n t r i g h t ) int Add(int left, int right) intAdd(intleft,intright)
  • 当口味不对的时候,会优先调用参数匹配 例如: A d d ( a , c ) Add(a,c) Add(a,c)调用 t e m p l a t e < t y p e n a m e T 1 , t y p e n a m e T 2 > template<typename T1, typename T2> template<typenameT1,typenameT2>
  • 当两个都没有的时候,会将就一样。例如: A d d ( a , c ) Add(a,c) Add(a,c)调用 i n t A d d ( i n t L e f t , i n t R i g h t ) int Add(int Left, int Right) intAdd(intLeft,intRight)

当然模版函数只是单参数的时候,我们传入两个不同类型的参数时,就会报错,编译器不知道推演哪一个?

类模版

typedef int DataType;
class Stack
{
public:
	Stack()
	{
		_array = (DataType*)malloc(sizeof(DataType) * 3);
		if (NULL == _array)
		{
			perror("malloc申请空间失败!!!");
			return;
		}
		_capacity = 3;
		_size = 0;
	}
	void Push(DataType data)
	{
		_array[_size] = data;
		_size++;
	}
	~Stack()
	{
		if (_array)
		{
			free(_array);
			_array = NULL;
			_capacity = 0;
			_size = 0;
		}
	}
private:
	DataType* _array;
	int _capacity;
	int _size;
};

如上述栈,在C语言中,如果我们想要栈中存不同数据。

int main()
{
	Stack st1; //int
	Stack st2; //double
	return 0;
}

例如我们想要一个存 i n t int int,一个存 d o u b l e double double,那我们就需要写两个栈了,由于这两个栈的代码都类似,那么在C++中,我们可以定义模版,栈的数据类型,有模版来代替,这样想要存什么类型,直接示例化什么类型的即可。

template<typename T>
class Stack
{
public:
	Stack()
	{
		_array = (T*)malloc(sizeof(T) * 3);
		if (NULL == _array)
		{
			perror("malloc申请空间失败!!!");
			return;
		}
		_capacity = 3;
		_size = 0;
	}
	void Push(T data)
	{
		_array[_size] = data;
		_size++;
	}
	~Stack()
	{
		if (_array)
		{
			free(_array);
			_array = NULL;
			_capacity = 0;
			_size = 0;
		}
	}
private:
	T* _array;
	int _capacity;
	int _size;
};

int main()
{
	Stack<int> st1; //int
	Stack<double> st2; //double
	return 0;
}

当然我们的模版也可以把声明和定义分开,但是注意: 模版的定义和声明要分离也分离在 .h 文件中,最好不要一个在 .h 文件 一个在 .cpp文件,这样会让编译的时间大大增加。
在这里插入图片描述

在这里插入图片描述
同时我们的T还要另外声明一次,不然编译器不知道T是哪来的。类域声明的时候我们要 S t a c k < i n t > Stack<int> Stack<int>这样写。因为此时我们的 S t a c k < i n t > Stack<int> Stack<int>才是我们的模版类型。

结言

本文只是简单介绍了模版的基本概念,后期学了更深的内容会持续更新…

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

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

相关文章

小技巧(更新中)

1.Pycharm使用小技巧pycharm的使用小技巧1---快速找到模块内的函数和类&#xff0c;快速定位查看的模块所在位置_pycharm怎么查找某个函数-CSDN博客 2. Python库之requirments Python库安装之requirements.txt, environment.yml_python requirements-CSDN博客 3.执行.sh脚本的…

N6 word2vec文本分类

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊# 前言 前言 上周学习了训练word2vec模型&#xff0c;这周进行相关实战 1. 导入所需库和设备配置 import torch import torch.nn as nn import torchvision …

10x Visium HD数据分析

–https://satijalab.org/seurat/articles/visiumhd_analysis_vignette 留意更多内容&#xff0c;欢迎关注微信公众号&#xff1a;组学之心 1.数据准备-Seurat Visium HD 数据是由特定空间排列分布的寡核苷酸序列在 2um x 2um 的网格&#xff08;bin&#xff09;中生成的。然…

15. Revit API: Transaction(事务)与 Failures(故障处理)

前言 UI讲完&#xff0c;回到DB这块儿。在Document那篇&#xff0c;提到增删改查操作都是在Document上&#xff0c;是对Documet进行操作。 看到“增删改查”这四个&#xff0c;想到什么了没有&#xff1f; 数据库&#xff08;DB&#xff09;嘛~话说那本经典的红皮数据库的书叫…

Python学习笔记34:进阶篇(二十三)pygame的使用之颜色与字体

前言 基础模块的知识通过这么长时间的学习已经有所了解&#xff0c;更加深入的话需要通过完成各种项目&#xff0c;在这个过程中逐渐学习&#xff0c;成长。 我们的下一步目标是完成python crash course中的外星人入侵项目&#xff0c;这是一个2D游戏项目。在这之前&#xff…

算法训练营day28--134. 加油站 +135. 分发糖果+860.柠檬水找零+406.根据身高重建队列

一、 134. 加油站 题目链接&#xff1a;https://leetcode.cn/problems/gas-station/ 文章讲解&#xff1a;https://programmercarl.com/0134.%E5%8A%A0%E6%B2%B9%E7%AB%99.html 视频讲解&#xff1a;https://www.bilibili.com/video/BV1jA411r7WX 1.1 初见思路 得模拟分析出…

【Python实战因果推断】19_线性回归的不合理效果9

目录 De-Meaning and Fixed Effects Omitted Variable Bias: Confounding Through the Lens of Regression De-Meaning and Fixed Effects 您刚刚看到了如何在模型中加入虚拟变量来解释不同组间的不同干预分配。但是&#xff0c;FWL 定理真正的亮点在于虚拟变量。如果您有大量…

鸿蒙架构之AOP

零、主要内容 AOP 简介ArkTs AOP 实现原理 JS 原型链AOP实现原理 AOP的应用场景 统计类&#xff1a; 方法调用次数统计、方法时长统计防御式编程&#xff1a;参数校验代理模式实现 AOP的注意事项 一、AOP简介 对于Android、Java Web 开发者来说&#xff0c; AOP编程思想并不…

【前端】包管理器:npm、Yarn 和 pnpm 的全面比较

前端开发中的包管理器&#xff1a;npm、Yarn 和 pnpm 的全面比较 在现代前端开发中&#xff0c;包管理器是开发者必不可少的工具。它们不仅能帮我们管理项目的依赖&#xff0c;还能极大地提高开发效率。本文将详细介绍三种主流的前端包管理器&#xff1a;npm、Yarn 和 pnpm&am…

错位情缘悬疑升级

✨&#x1f525;【错位情缘&#xff0c;悬疑升级&#xff01;关芝芝与黄牡丹的惊世婚约】&#x1f525;✨在这个迷雾重重的剧场&#xff0c;一场前所未有的错位大戏正悄然上演&#xff01;&#x1f440; 你没看错&#xff0c;昔日兄弟的前女友关芝芝&#xff0c;竟摇身一变成了…

axios使用sm2加密数据后请求参数多了双引号解决方法

axios使用sm2加密数据后请求参数多了双引号解决 背景问题描述解决过程 背景 因项目安全要求&#xff0c;需对传给后端的入参加密&#xff0c;将请求参数加密后再传给后端 前期将axios降低到1.6.7后解决了问题&#xff0c;但最近axios有漏洞&#xff0c;安全要求对版本升级&…

通过电压差判定无源晶振是否起振正确吗?

在电子工程中&#xff0c;无源晶振作为许多数字电路的基础组件&#xff0c;其是否成功起振对于系统的正常运行至关重要。然而&#xff0c;通过简单检测晶振两端的电压差来判断晶振是否工作&#xff0c;这一方法存在一定的误区&#xff0c;晶发电子将深入探讨这一话题&#xff0…

【AIGC】一、本地docker启动私有大模型

本地docker启动私有大模型 一、最终效果中英文对话生成代码 二、资源配置三、搭建步骤启动docker容器登录页面首次登录请注册登录后的效果 配置模型尝试使用选择模型选项下载模型选择适合的模型开始下载 试用效果返回首页选择模型中英文对话生成代码 四、附录资源监控 五、参考…

浮点类型使用陷阱

引言 当我们进行条件判断时,经常会遇到两个数是否相等的情况,但如果在程序中进行判断一个可以除尽的小数和数学上除出来所得的数是否相等时,就会神奇的发型居然不相等??! 遇到问题 看如下代码 double num5 2.7;//2.7double num6 8.1 / 3;//接近2.7System.out.println(n…

NAS免费用,鲁大师 AiNAS正式发布,「专业版」年卡仅需264元

7月10日&#xff0c;鲁大师召开新品发布会&#xff0c;正式发布旗下以“提供本地Ai部署和使用能力以及在线NAS功能”并行的复合软件产品&#xff1a;鲁大师 AiNAS。 全新的鲁大师 AiNAS将持续满足现如今大众对于数字化生活的全新需求&#xff0c;将“云存储”的便捷与NAS的大容…

学圣学最终的目的是:达到思无邪的状态( 纯粹、思想纯正、积极向上 )

学圣学最终的目的是&#xff1a;达到思无邪的状态&#xff08; 纯粹、思想纯正、积极向上 &#xff09; 中华民族&#xff0c;一直以来&#xff0c;教学都是以追随圣学为目标&#xff0c;所以中华文化也叫圣学文化&#xff0c;是最高深的上等学问&#xff1b; 圣人那颗心根本…

如何配置yolov10环境?

本文介绍如何快速搭建起yolov10环境&#xff0c;用于后续项目推理、模型训练。教程适用win、linux系统 yolo10是基于yolo8&#xff08;ultralytics&#xff09;的改进&#xff0c;环境配置跟yolo8几乎一模一样。 目录 第1章节&#xff1a;创建虚拟环境 第2章节&#xff1a;…

tesla p100显卡显示资源不足,api调用失败

&#x1f3c6;本文收录于《CSDN问答解惑-专业版》专栏&#xff0c;主要记录项目实战过程中的Bug之前因后果及提供真实有效的解决方案&#xff0c;希望能够助你一臂之力&#xff0c;帮你早日登顶实现财富自由&#x1f680;&#xff1b;同时&#xff0c;欢迎大家关注&&收…

数据结构JAVA

1.数据结构之栈和队列 栈结构 先进后出 队列结构 先进先出 队列 2.数据结构之数组和链表 数组结构 查询快、增删慢 队列结构 查询慢、增删快 链表的每一个元素我们叫结点 每一个结点都是独立的对象

浅谈“不要卷模型,要卷应用”

目录 1.概述 2.AI技术应用场景探索 3.避免超级应用陷阱的策略 3.1.追求DAU的弊端 3.2.平衡用户活跃度与应用实用性的策略 4.个性化智能体开发 4.1. 用户需求分析与数据收集 4.2. 技术选择与开发 4.3. 个性化算法设计 4.4. 安全性与隐私保护 4.5. 多渠道集成与响应机…