当前位置: 首页 > news >正文

C++学习(6)——模板

系列文章目录


文章目录

  • 系列文章目录
  • 一、函数模板
    • 1.函数模板的实例化
      • (1)隐式实例化
      • (2)显式实例化
    • 2.模板函数的特性
  • 二、类模板


一、函数模板

函数模板代表了一个函数系列,该函数模板与类型无关。在使用时被参数化,根据实参类型产生函数的特定类型版本。

使用格式如下,注意typename可以使用class替换!
template<typename T1, typename T2,…,typename Tn>
返回值类型 函数名(参数列表){}

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

函数模板只是一个蓝图,它本身并不是函数,是编译器用来推演生成具体类型函数的模具。所以其实模板就是将本来应该我们做的重复的事情交给了编译器。
在编译器编译阶段,编译器需要根据传入的实参类型来推演生成对应类型的函数以供调用。
比如:当用double类型使用函数模板时,编译器通过对实参类型的推演,将T确定为double类型,然后产生一份专门处理double类型的代码。对于其他类型实参也是如此。

1.函数模板的实例化

函数模板实例化:编译器根据所传参数的类型推演模板类型并生成对应函数。

(1)隐式实例化

编译器通过参数类型推测模板参数的实际类型

template<class T>
T Add(T left, T right)
{
	return left + right;
}
int main()
{
	int a=0, b=1;
	double c = 9.1, d = 5.2;
	cout << Add(a, b) << endl;
	cout << Add(c, d) << endl;
	return 0;
}

注意:如果所传两个实参类型不同会产生错位,因为编译器无法推演出满版参数的类型到底是两种类型中的哪一个。
在隐式实例化中,编译器不会对参数类型不同的参数做隐式类型转换

template<class T>
T Add(T left, T right)
{
	return left + right;
}
int main()
{
	int a = 9;
	double b = 2.3;
	cout << Add(a, b) << endl;
	return 0;
}

该情况有两种解决方法:1.使用显式实例化,直接指明模板参数的类型;2.对参数使用强制类型转换;

(2)显式实例化

在函数名后的<>中指定模板参数的实际类型,直接确定模板参数的类型,省去编译器推演过程。

int main(void)
{
 int a = 10;
 double b = 20.0;
 
 // 显式实例化
 Add<int>(a, b);
 return 0;
}

当使用显式实例化时,编译器可以根据指定的参数类型对类型不同的参数自动进行隐式类型转换
所以上述参数类型不同引发的问题得以解决:

下述代码输出结果为11

template<class T>
T Add(T left, T right)
{
	return left + right;
}
int main()
{
	int a = 9;
	double b = 2.3;
	cout << Add<int>(a, b) << endl;
	return 0;
}

2.模板函数的特性

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

// 专门处理int的加法函数
int Add(int left, int right)
{
 return left + right;
}
// 通用加法函数
template<class T>
T Add(T left, T right)
{
 return left + right;
}
void Test()
{
 Add(1, 2); // 与非模板函数匹配,编译器不需要特化
 Add<int>(1, 2); // 调用编译器特化的Add版本

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

// 专门处理int的加法函数
int Add(int left, int right)
{
 return left + right;
}
// 通用加法函数
template<class T1, class T2>
T1 Add(T1 left, T2 right)
{
 return left + right;
}
void Test()
{
 Add(1, 2); // 与非函数模板类型完全匹配,不需要函数模板实例化
 Add(1, 2.0); // 模板函数可以生成更加匹配的版本,编译器根据实参生成更加匹配的Add函数
}

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

二、类模板

与函数模板格式相似,唯一不同是用来泛化类
注意:T的作用域为整个类
格式如下:

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

使用类模板实现静态数组:

#define N 10
template<class T>
class test
{
public:
	T& operator[](int idx)
	{
		if (idx < N)
		{
			return arr[idx];
		}
	}
private:
	T arr[N];
};
int main()
{
	test<int> t;
	for (int i = 0; i < N; i++)
	{
		t[i] = i;
	}
	for (int i = 0; i < N; i++)
	{
		cout << t[i] << ' ';
	}
	cout << endl;
	return 0;
}

类模板通常使用显式实例化,它没有机会使用隐式实例化,这要求我们在使用类实例化对象时要同时实例化模板类。

相关文章:

  • C++重载运算符
  • 1027推免分享材料 备份
  • JavaScript---常用JS方法(utils.js)额外篇
  • 《CTF特训营》学习笔记——APK逆向基础
  • 一文带你了解怎样快速上手微信小程序开发
  • 基于注意力机制的深度协同推荐模型
  • 【Linux修炼】6.gcc/g++及Makefile【工具篇】
  • 【Linux】基本的指令(三)
  • 算法学习 | 贪心算法~通过局部最优的选择来得到整体最优解
  • 聊聊Spring Cloud Gateway 动态路由及通过Apollo的实现
  • Python爬虫入狱小技巧
  • java中判断集合是否为空
  • Vitepress搭建组件库文档(下)—— 组件 Demo
  • 计算多张图片的移位距离
  • 一起啃西瓜书(四)
  • 345-反转字符串中的元音字母
  • conda常用的命令
  • Dubbo 整合 Pinpoint 做分布式服务请求跟踪
  • Invalidate和postInvalidate的区别
  • Java,console输出实时的转向GUI textbox
  • JavaScript服务器推送技术之 WebSocket
  • JS函数式编程 数组部分风格 ES6版
  • node和express搭建代理服务器(源码)
  • rabbitmq延迟消息示例
  • WinRAR存在严重的安全漏洞影响5亿用户
  • 纯 javascript 半自动式下滑一定高度,导航栏固定
  • 第十八天-企业应用架构模式-基本模式
  • 关于Java中分层中遇到的一些问题
  • 基于 Babel 的 npm 包最小化设置
  • 利用jquery编写加法运算验证码
  • 模仿 Go Sort 排序接口实现的自定义排序
  • 前端面试总结(at, md)
  • 融云开发漫谈:你是否了解Go语言并发编程的第一要义?
  • 如何解决微信端直接跳WAP端
  • 如何用Ubuntu和Xen来设置Kubernetes?
  • ​低代码平台的核心价值与优势
  • #define,static,const,三种常量的区别
  • (Matalb时序预测)PSO-BP粒子群算法优化BP神经网络的多维时序回归预测
  • (SpringBoot)第二章:Spring创建和使用
  • (层次遍历)104. 二叉树的最大深度
  • (带教程)商业版SEO关键词按天计费系统:关键词排名优化、代理服务、手机自适应及搭建教程
  • (附源码)基于SpringBoot和Vue的厨到家服务平台的设计与实现 毕业设计 063133
  • (南京观海微电子)——COF介绍
  • (全注解开发)学习Spring-MVC的第三天
  • (一)80c52学习之旅-起始篇
  • .bat批处理(九):替换带有等号=的字符串的子串
  • .NET CF命令行调试器MDbg入门(四) Attaching to Processes
  • .NET 跨平台图形库 SkiaSharp 基础应用
  • .net6+aspose.words导出word并转pdf
  • .NETCORE 开发登录接口MFA谷歌多因子身份验证
  • /bin/bash^M: bad interpreter: No such file or directory
  • [ vulhub漏洞复现篇 ] Django SQL注入漏洞复现 CVE-2021-35042
  • [AIGC] Kong:一个强大的 API 网关和服务平台
  • [Android 数据通信] android cmwap接入点
  • [C++]命名空间等——喵喵要吃C嘎嘎