简单介绍C++中的模板

news2024/10/6 16:21:30

目录

一、泛型编程

泛型编程的概念:

泛型编程举例:

二、函数模板

函数模板的概念:

函数模板的格式:

函数模板的实例化:

隐式实例化:

显式实例化:

模板参数的匹配原则:

三、类模板

类模板的格式定义:

类模板的举例:

类模板的实例化:


当我们在编写程序时可能会遇见这样的问题:交换函数是使用频率非常高的函数,当我们想在一个工作台下同时交换char、int、double类型的数据时,我们要怎么做呢?

在C语言中,我们只能通过不同的函数名,对数据类型不同、函数功能相同的函数进行区分。

void Swapi(int left, int right) {//此处省略函数体}
void Swapd(double left, double right) {//此处省略函数体}
void Swapc(char left, char right){//此处省略函数体}
……

由于C++引入了函数重载的概念,使用相同的函数名,编译器可以根据形参的数据类型不同进行区分。

void Swap(int& left, int& right) {//此处省略函数体}
void Swap(double& left, double& right) {//此处省略函数体}
void Swap(char& left, char& right){//此处省略函数体}
……

使用函数重载虽然可以实现,但有几个不好的地方:

  1. 函数从在仅仅时类型不同,代码复用率低,有新类型出现时需要用户自己增加对应函数
  2. 代码可维护性低,当代码出错时,可能需要对所有的代码都需要修改

仔细观察会发现,上述代码只有数据类型不同,其他代码实现都相同。那么是否可以将代码作为模具,将数据类型设为X(未知数据类型),在具体调用时,再将实际的数据类型和X进行替换,就可以实现一份代码,解决函数重载带来的所有问题。因此,引入了泛型编程的思想。

一、泛型编程

泛型编程的概念:

泛型编程是一种编程范式,它的目的是提高代码的重用性和灵活性。泛型编程允许程序员使用不同的数据类型来实现相同的算法和数据结构,从而编写更加通用和可扩展的代码。

泛型编程举例:

实现一个通用的交换函数

//template模板关键字,typename模板中数据类型不是固定的,需要编译器自动推导
template<typename T>
void Swap(T& left, T& right)
{
	T temp = left;
	left = right;
	right = temp;
}

int main()
{
	int a = 10, b = 20;
	double c = 10.12, d = 20.34;
	Swap(a, b);
	Swap(c, d);
	cout << "a:" << a << "    " << "b:" << b << endl;
	cout << "c:" << c << "    " << "d:" << d << endl;

	return 0;
}

二、函数模板

函数模板的概念:

函数模板是一种通用的函数定义形式,允许定义一个接受任意类型参数的函数。它的定义形式类似于一个普通函数,但是使用了类型占位符(通常为T)来代替具体类型。在函数调用时,编译器会根据调用时传递的参数类型来确定T的具体值并生成相应的函数实例。

函数模板的格式:

template<typename T1, typename T2,......,typename Tn>
返回值类型 函数名(参数列表) {}
template<typename T>//typename是用来定义模板参数关键字,也可以使用class
void Swap(T& left, T& right)
{
	T temp = left;
	left = right;
	right = temp;
}

函数模板的实例化:

函数模板并不是实际存在的,只有当系统调用时,才会根据传递过去的实际类型进行实例化。分为隐式实例化和显式实例化

隐式实例化:

编译器根据实参,推演模板参数的实际类型

template<class T>
T Add(const T& left, const T& right) { return left + right; }
int main()
{
	int a1 = 10, a2 = 20;
	double d1 = 10.0, d2 = 20.0;
	Add(a1, a2);//实参是int,编译器将T替换成int,实例化出具体函数
	Add(d1, d2);
    
    //Add(a1, d1);//注意:在模板中,编译器一般不会进行类型转换操作,实参是int和double两种类型,编译器会报错

    //想解决这种问题有两种方式:1、类型转换;2、显式实例化
    Add(a1, (int)d1);

	return 0;
}

显式实例化:

在函数名后,用<>指定模板参数的实际类型

template<class T>
T Add(const T& left, const T& right) { return left + right; }
int main()
{
	int a = 10;
	double b = 20.4;

	// 显式实例化
	Add<int>(a, b);//如果实参类型和指定的类型不匹配,会进行类型转换,失败会报错

	return 0;
}

模板参数的匹配原则:

一个非模板参数和一个同名的函数模板同时存在,如果其他条件都相同,首选非模板参数

//非模板函数
int Add(const int& left, const int& right) { return left + right; }

//模板函数
template<class T>
T Add(const T& left, const T& right) { return left + right; }

int main()
{

	Add(1, 2);//首选非模板函数
	Add<int>(1, 2);//显示实例化,会选择模板函数

	return 0;
}

一个非模板函数和一个同名的函数模板同时存在,函数模板生成的函数更加匹配,会选择函数模板

//非模板函数
int Add(const int& left, const int& right) { return left + right; }

//模板函数
template<class T1,class T2>
T1 Add(const T1& left, const T2& right) { return left + right; }

int main()
{

	Add(1, 2);//与非模板函数参数类型相同,首选非模板函数
	Add(1, 2.0);//与模板函数生成的函数更匹配,选择模板函数

	return 0;
}

函数模板不能进行隐式类型转换,非模板函数可以进行隐式类型转换

三、类模板

类模板的格式定义:

template<class T1, class T2, ..., class Tn>
class 类模板名
{
    // 类内成员定义
};

类模板的举例:

//模拟vector
//vextor不是一个具体的类,编译器会根据实例化的具体类型从而生成具体类的容器
template<class T>
class vector
{
public:
	vector(size_t capacity = 10)
		:_pData(new T[capacity])
		,_size(0)
		,_capacity(capacity)
	{ }
	
	//……以下细节省略
private:
	T* _pData;
	size_t _size;
	size_t _capacity;
};

类模板的实例化:

template<class T>
class vector
{
public:
	vector(size_t capacity = 10)
		:_pData(new T[capacity])
		,_size(0)
		,_capacity(capacity)
	{ }
	
	//……以下细节省略
private:
	T* _pData;
	size_t _size;
	size_t _capacity;
};

int main()
{
	//使用显式实例化指定类型
	vector<int> v1;

	return 0;
}

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

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

相关文章

PyQt5组件之QLabel显示图像和视频

目录 一、显示图像和视频 1、显示图像 2、显示视频 二、QtDesigner 窗口简单介绍 三、相关函数 1、打开本地图片 2、保存图片到本地 3、打开文件夹 4、打开本地文本文件并显示 5、保存文本到本地 6、关联函数 7、图片 “.png” | “.jpn” Label 自适应显示 一、显…

C++ 之 线性插值 贝塞尔曲线 非线性动画

非线性动画在程序&#xff0c;游戏和动画中运用非常广泛&#xff0c;那么我们应该如何实现&#xff1f; 非线性动画上的点在s-t图像上非线性&#xff0c;即不为一次函数&#xff0c;实则为处处连续的曲线 对于此曲线可模拟&#xff0c;这里我们用贝塞尔曲线 一&#xff0c;基本…

Azure DevOps基于 Net6.0 的 WPF 程序如何进行持续集成、持续编译

正文 1&#xff0c; Azure DevOps 创建项目 Project name&#xff1a;”NetCore_WPF_Sample“ Visibility&#xff1a;”Private“&#xff08;根据实际项目需求&#xff09; Version control&#xff1a;”Git“ Work item process&#xff1a;”Agile“ 点击 ”Create“…

【linux】2 软件管理器yum和编辑器vim

目录 1. linux软件包管理器yum 1.1 什么是软件包 1.2 关于rzsz 1.3 注意事项 1.4 查看软件包 1.5 如何安装、卸载软件 1.6 centos 7设置成国内yum源 2. linux开发工具-Linux编辑器-vim使用 2.1 vim的基本概念 2.2 vim的基本操作 2.3 vim正常模式命令集 2.4 vim末行…

【设计模式】MVC 模式

MVC 模式代表 Model-View-Controller&#xff08;模型-视图-控制器&#xff09; 模式。这种模式用于应用程序的分层开发。 Model&#xff08;模型&#xff09; - 模型代表一个存取数据的对象或 JAVA POJO。它也可以带有逻辑&#xff0c;在数据变化时更新控制器。View&#xff…

【爬虫】爬取旅行评论和评分

以马蜂窝“普达措国家公园”为例&#xff0c;其评论高达3000多条&#xff0c;但这3000多条并非是完全向用户展示的&#xff0c;向用户展示的只有5页&#xff0c;数了一下每页15条评论&#xff0c;也就是75条评论&#xff0c;有点太少了吧&#xff01; 因此想了个办法尽可能多爬…

Linux 终端命令之文件浏览(2) more

Linux 文件浏览命令 cat, more, less, head, tail&#xff0c;此五个文件浏览类的命令皆为外部命令。 hannHannYang:~$ which cat /usr/bin/cat hannHannYang:~$ which more /usr/bin/more hannHannYang:~$ which less /usr/bin/less hannHannYang:~$ which head /usr/bin/he…

最新智能AI系统+ChatGPT源码搭建部署详细教程+知识库+附程序源码

近期有网友问宝塔如何搭建部署AI创作ChatGPT&#xff0c;小编这里写一个详细图文教程吧。 使用Nestjs和Vue3框架技术&#xff0c;持续集成AI能力到AIGC系统&#xff01; 增加手机端签到功能、优化后台总计绘画数量逻辑&#xff01;新增 MJ 官方图片重新生成指令功能同步官方 …

nginx负载均衡配置过程

一、环境说明 主机名IPnginx服务器nginx-server192.168.198.141web页面1web1192.168.198.100web页面2web2192.168.198.200 关闭所有主机的防火墙和Selinux服务 二、配置过程 自定义页面 自定义web1和web2的页面 主配置文件 查看nginx的主配置文件 vim /usr/local/nginx/c…

全球八分之一的河流受到缺氧影响

一项全球研究发现&#xff0c;世界各地河流中的溶解氧含量低得危险。缺氧的真实发生率可能更高。 小型、低梯度的城市河流&#xff0c;例如图中北卡罗来纳州的那条河流&#xff0c;是最容易缺氧的河流之一。图片来源&#xff1a;乔安娜布拉扎克 2023 年 3 月&#xff0c;《卫报…

LeetCode--HOT100题(29)

目录 题目描述&#xff1a;19. 删除链表的倒数第 N 个结点&#xff08;中等&#xff09;题目接口解题思路代码 PS: 题目描述&#xff1a;19. 删除链表的倒数第 N 个结点&#xff08;中等&#xff09; 给你一个链表&#xff0c;删除链表的倒数第 n 个结点&#xff0c;并且返回链…

Microsoft365家庭版1年订阅新功能及版本对比

Microsoft 365可帮助您工作、学习、组织、连接和创&#xff0c;只需一项方便的订阅&#xff0c;即可尽享具有 Microsft 365 的6款精品应用、可同时登录5 台设备&#xff08;包括 Windows、macOS、iOS 和 Android 设备&#xff09;、高级安全性等&#xff0c;并且可以自由管理授…

升级STM32电机PID速度闭环编程:从F1到F4的移植技巧与实例解析

引言&#xff1a; 在嵌入式系统开发中&#xff0c;STM32系列微控制器广泛应用于各种应用领域。而对于直流有刷电机的控制&#xff0c;PID速度闭环是一种常用的控制方式。本文将以此为例&#xff0c;探讨如何从STM32F1系列移植到STM32F4系列&#xff0c;并详细介绍HAL库在不同型…

渗透测试验证码爆破实操

一、准备工具 captcha-killer-modified 下载路径 https://github.com/f0ng/captcha-killer-modified https://github.com/f0ng/captcha-killer-modified/releases/download/0.21-beta/captcha-killer-modified-0.21-beta-jdk11.jar 二、安装工具 burp安装captcha-killer-modif…

登录验证码实现

Hutool代码改造 Hutool 有参考文档&#xff1b;很多工具类&#xff1b;把一些功能都封装好&#xff1b;都不用你自己去写&#xff1b;直接调用它的工具类 它这里会详细告诉你引入方式Hutool <dependency><groupId>cn.hutool</groupId><artifactId>hu…

【第二阶段】kotlin语言的内联-inline关键字

1.函数如果没有使用lambda作为参数&#xff0c;就不需要声明成内联 2.函数如果使用lambda作为参数&#xff0c;就需要声明成内联&#xff0c;如果不使用内联&#xff0c;在调用端会生成多个对象来完成lambda的调用&#xff0c;会造成性能的损耗 3.函数如果使用lambda作为参数&a…

模板Plus【完整版】

文章目录 1.非类型模板参数的引入2.标准库和普通数组3.模板的特化3.1介绍3.2代码讲解3.3画图讲解 4.类、函数模板特化初识5.全特化与偏特化6.模板不能分离编译1.typename的使用2.预处理相关知识3.为什么不能分离编译&#xff1f;4.怎么解决&#xff1f;5.代码详解1.vector.h2.v…

实战篇之基于二进制思想的用户标签系统(Mysql+SpringBoot)

一&#xff1a; 计算机中的二进制 计算机以二进制表示数据&#xff0c;以表示电路中的正反。在二进制下&#xff0c;一个位只有 0 和 1 。逢二进一 位。类似十进制下&#xff0c;一个位只有 0~9 。逢十进一位。 二&#xff1a; 进制常用运算 &#xff08;位运算&#xff09;…

QT之时钟

QT之时钟 会用到一个时间类:qtime 定时类:qtimer #------------------------------------------------- # # Project created by QtCreator 2023-08-13T10:49:31 # #-------------------------------------------------QT += core guigreaterThan(QT_MAJOR_VERSION,…