模板(一)

news2024/11/13 15:38:05

文章目录

  • 模板(一)
    • 1.泛型编程
    • 2.函数模板
      • 2.1函数模板概念
      • 2.2函数模板格式
      • 2.3函数模板的原理
      • 2.4函数模板的实例化
        • 2.4.1隐式实例化
        • 2.4.2显式实例化
      • 2.5模板参数的匹配原则
    • 3.类模板
      • 3.1类模板的定义格式
      • 3.2类模板的实例化

模板(一)

1.泛型编程

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

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. 代码的可维护性比较低,一个出错可能所有的重载均出错

那能否告诉编译器一个模子,让编译器根据不同的类型利用该模子来生成代码呢?

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

在这里插入图片描述

2.函数模板

2.1函数模板概念

函数模板代表了一个函数家族,该函数模板与类型无关。

在使用时被参数化,根据实参类型产生函数的特定类型版本。

2.2函数模板格式

template<typename T1, typename T2,…,typename Tn>

返回值类型 函数名(参数列表){}

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std;

template<typename T>
void Swap(T& left, T& right)
{
	T temp = left;
	left = right;
	right = temp;
}

int main()
{
	int a = 10;
	int b = 30;
	cout << "a = " << a << " ";
	cout << "b = " << b << " ";
	cout << endl;

	Swap(a,b);
	cout << "a = " << a << " ";
	cout << "b = " << b << " ";
	return 0;
}

在这里插入图片描述

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

2.3函数模板的原理

函数模板是一个蓝图,它本身并不是函数,是编译器用使用方式产生特定具体类型函数的模具。

所以其实模板就是将本来应该我们做的重复的事情交给了编译器。

在这里插入图片描述

在编译器编译阶段,对于模板函数的使用,编译器需要根据传入的实参类型来推演生成对应类型的函数,以供调用。

比如:当用double类型使用函数模板时,编译器通过对实参类型的推演,将T确定为double类型,然后产生一份专门处理double类型的代码,对于字符类型也是如此。

2.4函数模板的实例化

用不同类型的参数使用函数模板时,称为函数模板的实例化。

模板参数实例化分为:隐式实例化和显式实例化。

2.4.1隐式实例化

隐式实例化:让编译器根据实参推演模板参数的实际类型。

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std;

template<class T>
T Add(const T& left, const T& right)
{
	cout << left + right << endl;
	return 0;
}
int main()
{
	int a1 = 10, a2 = 20;
	double d1 = 10.11, d2 = 20.11;
	Add(a1, a2);
	Add(d1, d2);
	Add(a1, (int)d1);  //不同类型需要用户自己来强制转化
	return 0;
}

在这里插入图片描述

2.4.2显式实例化

显式实例化:在函数名后的**< >**中指定模板参数的实际类型。

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std;

template<class T>
T Add(const T& left, const T& right)
{
	cout << left + right << endl;
	return 0;
}
int main(void)
{
	int a = 10;
	double b = 20.11;
	Add<int>(a, b);  // 显式实例化
	Add<double>(a, b);
	return 0;
}

在这里插入图片描述

如果类型不匹配,编译器会尝试进行隐式类型转换,如果无法转换成功编译器将会报错

2.5模板参数的匹配原则

  1. 一个非模板函数可以和一个同名的函数模板 同时存在,而且该函数模板还可以被实例化为这个非模板函数
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std;

int Add(int left, int right)  //专门处理int的加法函数
{
	cout << left + right << endl;
	return 0;
}

template<class T>
T Add(T left, T right)  //通用加法函数
{
	cout << left + right << endl;
	return 0;
}

int main(void)
{
	Add(1, 2); // 与非模板函数匹配,编译器不需要特化
	Add<int>(1, 2); // 调用编译器特化的Add版本
	return 0;
}

在这里插入图片描述

  1. 对于非模板函数和同名函数模板,如果其他条件都相同,在调动时会优先调用非模板函数而不会从该模板产生出一个实例。如果模板可以产生一个具有更好匹配的函数, 那么将选择模板.
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std;

int Add(int left, int right) 
{
	cout << left + right << endl;
	return 0;
}

template<class T>
T Add(T left, T right) 
{
	cout << left + right << endl;
	return 0;
}

int main(void)
{
	Add(1, 2); 
	Add(1, 2.0);
	return 0;
}

在这里插入图片描述

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

3.类模板

3.1类模板的定义格式

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

举例:

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std;

template<typename T>
class Vector  // 注意:Vector不是具体的类,是编译器根据被实例化的类型生成具体类的模具
{
public:
	Vector(size_t capacity = 10)
		: _pData(new T[capacity])
		, _size(0)
		, _capacity(capacity)
	{}

	~Vector();  //使用析构函数演示:在类中声明,在类外定义。

	void PushBack(const T& data)void PopBack();

	size_t Size() { return _size; }

	T& operator[](size_t pos)
	{
		assert(pos < _size);
		return _pData[pos];
	}

private:
	T* _pData;
	size_t _size;
	size_t _capacity;
};

template <class T>  // 注意:类模板中函数放在类外进行定义时,需要加模板参数列表
Vector<T>::~Vector()
{
	if (_pData)
		delete[] _pData;
	_size = _capacity = 0;
}

3.2类模板的实例化

类模板实例化与函数模板实例化不同,类模板实例化需要在类模板名字后跟 <>,然后将实例化的类型放在**<>**中即可,类模板名字不是真正的类,而实例化的结果才是真正的类。

// Vector类名,Vector<int>才是类型
Vector<int> s1;
Vector<double> s2;

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

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

相关文章

25.7 MySQL 数据库和表的基本操作

1. 基础知识 1.1 一条数据的存储过程 存储数据确实是处理数据的基石, 只有确保数据被准确无误且有条理地存储, 我们才能对其进行深入的处理和细致的分析. 否则, 这些数据就像是一团毫无章法的乱麻, 让我们难以捉摸其内在的逻辑和价值.那么, 如何才能够将用户那些与经营紧密相关…

人工智能时代如何高效完成营销内容计划

智能对话升级&#xff01;【Kompas AI】AI对话助手&#xff0c;让沟通更高效 在人工智能时代&#xff0c;要高效完成营销计划&#xff0c;我们可以利用人工智能的多种能力来增强营销策略的精准度和执行效率。借助人工智能的力量&#xff0c;企业不仅可以提高营销计划的执行效率…

Rust高级爬虫:如何利用Rust抓取精美图片

引言 在当今信息爆炸的时代&#xff0c;互联网上的图片资源丰富多彩&#xff0c;而利用爬虫技术获取这些图片已成为许多开发者的关注焦点。本文将介绍如何利用Rust语言进行高级爬虫编程&#xff0c;从而掌握抓取精美图片的关键技术要点。 Rust爬虫框架介绍 Rust语言生态中有…

一文说清:AI大模型在制造业中的应用类型

在过去的几年里&#xff0c;全球制造业的竞争格局正在发生重构&#xff0c;数字化和智能化成为推动变革的关键力量。AI 大模型作为一种通用人工智能技术&#xff0c;其革命性特征体现在能够生成代码、构建人机交互新模式&#xff0c;并与产品研发、工艺设计、生产作业、产品运营…

2024软考

报考链接&#xff1a; 中国计算机技术职业资格网 (ruankao.org.cn) 报名有效时间&#xff1a; 天津2024-03-24 09:00 ~ 2024-04-02 17:00 河北2024-03-20 09:30 ~ 2024-03-26 17:00 山西2024-03-18 14:30 ~ 2024-04-02 11:30 宁波2024-03-20 10:00 ~ 2024-03-26 16:00 辽宁…

C语言调用云端 Python接口

利用C语言调用阿里云Python接口&#xff0c;来实现垃圾的智能识别 文章目录 利用C语言调用阿里云Python接口&#xff0c;来实现垃圾的智能识别1、如何开启阿里云服务2、实验程序介绍2.1 py程序改造2.2 c语言调用py2.3 测试代码 3、实验结果 1、如何开启阿里云服务 大家可以自行…

RHCE作业:搭建web网站

综合练习&#xff1a; 请给openlab搭建web网站 网站需求&#xff1a; 1.域名访问网站 基于域名www.openlab.com可以访问网站内容为 welcome to openlab!!! 2.创建界面 给该公司创建三个子界面分别显示学生信息&#xff0c;教学资料 和缴费网站&#xff0c;基于www.openlab.com…

【精简】Spring笔记

文章目录 跳转链接&#xff08;学习路线&#xff09;及前言&#xff08;更新中&#xff09; 快速入门配置文件详解依赖注入(bean实例化)自动装配集合注入使用spring加载properties文件容器注解开发bean管理注解开发依赖注入第三方bean整合mybatis整合junit AOP入门案例切入点表…

【git分支管理策略】如何高效的管理好代码版本

目录 1.分支管理策略 2.我用的分支管理策略 3.一些常见问题 1.分支管理策略 分支管理策略就是一些经过实践后总结出来的可靠的分支管理的办法&#xff0c;让分支之间能科学合理、高效的进行协作&#xff0c;帮助我们在整个开发流程中合理的管理好代码版本。 目前有两套Git…

奇偶校验|ECC内存|海明码

前言 大家好&#xff0c;我是jiantaoyab&#xff0c;本篇文章给大家介绍数据出错和有什么方法能减少出错。 单比特翻转 由于硬件故障或其他原因&#xff0c;内存或其他存储设备中的单个比特位发生随机变化的现象。 例如&#xff0c;原本存储为1的位可能变为0&#xff0c;或…

放弃 Rust 选择 Zig,Xata 团队推出 pgzx —— 计划使用 Zig 开发基于 PG 的分布式数据库

Summary Xata 公司在基于 PostgresSQL 开发自己的分布式数据库&#xff0c;出于 Zig 和 C 语言以及 PostgreSQL 的 API 有更好的互操作性的考虑&#xff0c;他们选择了 Zig 而非当红炸子鸡语言 Rust。他们的博客文章中对 pgzx 进行了介绍。让我们来看下他们对 Zig 和 Rust 语言…

创建多节点 k8s 集群

主机IP系统master192.168.2.15ubuntu20.04 x64 2C 4GWorker1192.168.2.16ubuntu20.04 x64 2C 4GWorker1192.168.2.18ubuntu20.04 x64 2C 4G 使用 iterm2 连接四台服务器 command shift i 同时操作 初始化配置 关闭防火墙 systemctl stop firewalld systemctl disable firewa…

Qt篇——Qt无法翻译tr()里面的字符串

最近遇到使用Qt语言家翻译功能时&#xff0c;ui界面中的中文都能够翻译成英文&#xff0c;但是tr("测试")这种动态设置给控件的中文&#xff0c;无法翻译&#xff08;lang_English.ts文件中的翻译已经正确添加了tr()字符串的翻译&#xff09;。 上网搜了很多资料&am…

Redis(十八)Redlock算法

文章目录 自研锁逻辑lock加锁关键逻辑 Redlock红锁算法自研锁存在的问题Redlock算法设计理念RedisonRedisson使用案例Redisson源码分析多机案例 自研锁逻辑 按照JUC里面java.util.concurrent.locks.Lock接规范编写 lock加锁关键逻辑 加锁的Lua脚本&#xff0c;通过redis里面的…

vue3+vite - 报错 import.meta.glob() can only accept string literals.(详细解决方案)

报错说明 在vue3+vite项目中,解决报错: [plugin:vite:import-analysis] import.meta.glob() can only accept string literals. 如果我们报错差不多,就可以完美搞定这个错误。 解决教程 这个错误,是因为

【笔记】MJ Prompt

参数 --chaos 10 or --c 10, 0-10, defalut 0 --quality 1 or --q, 0.25-1, defalut 1 --iw 2, 0.5-2, --stylize 100 or --s 100, 0-1000, defalut 100 --cref URL --cw 100, 0-100stylize 风格化&#xff0c;MJ不同的出图模式&#xff0c;有默认的艺术风格&#xff0c;该值…

TCP协议中的传输控制机制图文详解「重传机制」「流量控制」「拥塞控制」

目录 TCP重传机制 超时重传 快速重传 SACK 方法 Duplicate SACK TCP 流量控制 滑动窗口 累积确认 窗口大小由哪一方决定&#xff1f; 接收窗口和发送窗口的大小是相等的吗&#xff1f; 流量控制 窗口关闭的后果 糊涂窗口综合症 TCP拥塞处理 为什么要有拥塞控制呀&#xff0c;不…

LinkedIn账号为什么被封?被封后如何解决?

近期会有一些小伙伴说自己遇到了帐号无法登录的情况&#xff0c;其实出现领英帐号被封号(被限制登录)主要会有两类情况&#xff0c;今天就给大家分享一下如果被封该如何解决&#xff0c;强烈建议收藏。 在电脑领英官网或者手机领英APP上&#xff0c;输入领英帐号密码点击登录后…

力扣● 84.柱状图中最大的矩形

84.柱状图中最大的矩形 需要找到元素i的上一个更小的元素leftmin和下一个更小的元素rightmin&#xff0c;这样leftmin和rightmin之间的元素都比当前元素i更大&#xff0c;那么矩形的宽就是中间的这些元素&#xff1a;可以从leftmin1延伸到rightmin-1&#xff0c;长即为height[i…

rancher2.6部署

rancher2.6部署 1、准备环境镜像 2、部署3、密码获取密码设置新密码 4、设置语言5、导入已有集群 1、准备 环境 docker-ce-20.10.23-3.el8.x86_64.rpm以及依赖rpm kubernetes&#xff1a;v1.23.17 镜像 &#xff08;rancher和k8s有个版本对应关系&#xff0c;rancher2.5就不…