c++基础篇(三)——模板初阶

本文详细介绍了C++中的函数模板和类模板,包括它们的提出背景、概念与使用、实例化过程。通过函数模板,可以实现对任意类型的数据进行交换,避免了大量代码冗余。同时,类模板则允许我们创建与类型无关的类,提供了一种泛型编程的能力。文章通过实例解析了模板的工作原理,并讨论了隐式和显式实例化的区别。
摘要由CSDN通过智能技术生成

作者介绍:

关于作者:东条希尔薇,一名喜欢编程的在校大学生
主攻方向:c++和linux
码云主页点我
本系列仓库直通车
作者CSDN主页地址

印刷术是中国四大发明之一,它极大地便利了古代人对于读书的需求。

设想,如果我们没有印刷术的话,我们要传播书籍该怎么做?我们必须要把这本书亲自手抄几万份后传播,这样的传播方式不仅非常的繁琐,而且浪费了很多不必要的人力

我们有印刷术就会方便许多,我们只需要抄一遍书上的内容,把它抄在一个模子上,然后使用这个模板,就能很轻松的把它复印几万份

而我们今天讲的内容,和古代的印刷术有异曲同工之妙

在这里插入图片描述

函数模板提出背景

假如我们要实现一个函数,这个函数要实现两个变量的交换,我们可以轻松写出以下代码

void Swap(int& rx,int& ry)
{
	int tmp=rx;
	rx=ry;
	ry=tmp;
}

但这个函数会有一个问题:我们只能交换整数类型,那么我们要交换其它类型的数又该怎么办呢?

我们可能想到,把每个类型都写一遍不就行了?

void Swap(int& rx,int& ry)
{
	int tmp=rx;
	rx=ry;
	ry=tmp;
}

void Swap(float& rx,float& ry)
{
	float tmp=rx;
	rx=ry;
	ry=tmp;
}

void Swap(double& rx,double& ry)
{
	double tmp=rx;
	rx=ry;
	ry=tmp;
}

这样每个类型写一个函数,会造成大量的代码冗余,而且对于自定义类型,我们根本不能确定到底要写多少个这样的函数

所以,在c++里面引入了函数模板的概念

函数模板的概念与使用

函数模板代表了一个函数家族,该函数模板与类型无关,它会根据实参自动推导自己的参数类型

拥有模板也是c++能支持泛型编程的基础,它也是STL实现的基础

使用格式:

template<class T1,class T2,.....class Tn>

//或者是typename T1....
//T1作为模板名,可以随意修改,不过一般都用T来表示

在上面一行代码完成后,下面要立即跟上一个模板函数

我们有了函数模板,就能让上面的swap函数支持任意类型,并且只有一份函数源码

template<class T>

void swap(T& rx,T& ry)
{
	T tmp=rx;
	rx=ry;
	ry=tmp;
}

函数模板原理及其实例化

我们知道了函数模板能够实现所有类型的使用,那么函数模板算一个函数吗?

我们可以通过观察不同类型函数的地址来观察

观察其反汇编代码

在这里插入图片描述
我们可以观察到,每次调用函数时,对应的swap函数地址是不一样的

我们可以得出结论,模板函数并不是一个函数

函数模板需要通过实例化来让对应参数使用其函数

实例化:模板函数根据不同的参数类型,来推演出它的参数类型,然后专门处理出一个针对此类型的函数代码

而实例化方式分为两种:隐式实例化显式实例化

隐式实例化

编译器根据实参,自动推导出参数的实际类型

template<class T>

void Swap(T& x, T& y)
{
	T tmp = x;
	x = y;
	y = tmp;
}

int main()
{
	int a = 2;
	int b = 3;
	float c = 3.3f;
	float d = 4.4f;
	Swap(a, b);
	
	Swap(c, d);
	return 0;
}

但注意:不能把不同类型的参数传入一个函数模板中,这样编译器就不知道这个模板到底推导成什么类型了

Swap(a,d);//int和float类型混合,报错

显式实例化

在函数名后加上**<类型名>**

Swap<int>(a,b);
Swap<int>(a,d);//这里不同类型使用不会报错,而是会发生隐式类型转换为<>内的类型

实例化原则:

对于非模板函数和函数模板同名的情况,调用时如果类型与非模板参数完全相同,将会优先调用非模板函数



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

int main()
{
	int a = 2;
	int b = 3;
	float c = 3.3f;
	float d = 4.4f;
	Swap(a, b);//调用非模板
	
	Swap(c, d);//调用模板
	return 0;
}

类模板

与函数模板类似,并不是一个真正的类型,而是根据不同类型推导出来的

使用方式:在类最上面使用template,类内部参数可以使用其模板

template<class T>
class Stack//栈类
{
public:
	void push(T n)
	{
		arr[top]=n;
		top++;
		size++;
	}
private:
	T *arr;
	int tmp;
	int cap;
}

注意以下几点

如果类成员函数在类外实现,必须要在每个函数前面加上template

类模板只能显式实例化

  • 31
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 21
    评论
评论 21
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

东条希尔薇

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值