模版初阶与STL

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; }

我们看上面这段代码,以前C语言的话,要实现不同类型变量的交换就要写多个函数
但是在C++中就可以告诉编译器一个模子,让编译器根据不同的类型利用该模子来生成代码
泛型编程:编写与类型无关的通用代码,是代码复用的一种手段。模板是泛型编程的基础。
模版又分为函数模版和类模版

2.函数模版

template<typename T>
void Swap(T& t1, T& t2)
{
	T tmp = t1;
	t1 = t2;
	t2 = tmp;
}
int main()
{
	int a1 = 0;
	int a2 = 1;
	Swap(a1, a2);
	cout << a1 << ' ' << a2 << endl;
	double b1 = 0.2;
	double b2 = 1.4;
	Swap(b1, b2);
	cout << b1 << ' ' << b2 << endl;
	return 0;
}

直接看代码,这里有两个关键字,为template和typename,他俩的作用主要是将类型命名为T
根据传入参数,来推测T的类型,这个叫做推演
其实并不是只调用的一个函数,而是调用的两个函数,为int时会建立T为int的函数,为double时会建立T为double的函数,这叫函数模版的实例化
所以说这并不会提高效率,麻烦的只是编译器了,但是方便的程序员就可以了
还有就是typename可以用class代替,两个是一样的作用在这里,但不能用struct代替
在这里插入图片描述
这一段代码会出问题主要是因为编译器不知道T是什么类型,你这样传过去,T既可以是int也可以是double,所以编译器会出错
处理方法一:将一个进行强制类型转换

template<typename T>
T Add(const T& t1,const T& t2)
{
	return t1 + t2;
}
int main()
{
	int a1 = 0;
	double a2 = 3.3;
	Add(a1, (int)a2);
	return 0;
}

如图我们将a2这个double类型强制类型转换,因为强制类型转换会生成临时变量,临时变量又具有常性,所以我们要用const修饰,在函数那里,所以说,如果有引用和指针的,如果不修改值的话,还是用const加上吧,不然很容易发生权限的缩小

template<typename T>
T Add(const T& t1,const T& t2)
{
	return t1 + t2;
}
int main()
{
	int a1 = 0;
	double a2 = 3.3;
	Add<int>(a1,a2);
	return 0;
}

在这里插入图片描述

方法二就是显示实例化了,就是在函数名后面,参数前面加上就表示直接认为T为int了,那这样的话,a2这个double类型就会发生隐式类型转换了

template<typename T1,class T2>
auto Add(const T1& t1, const T2& t2)
{
	return t1 + t2;
}
int main()
{
	int a1 = 0;
	double a2 = 3.3;
	cout << Add(a1, a2);
	return 0;
}

在这里插入图片描述
第三种方法就是在定义一个T,多对一个类型命名,那这样就可以根据int推出T1为int,根据为double类型推出T2为double,然后函数返回值不知道为什么好的话就用auto吧,自动判断,因为你不知道T1与T2谁为double,不知道返回谁好

int Add(int a1, int a2)
{
	cout << "int Add(int a1, int a2)" << endl;
	return a1 + a2;
}
template<typename T>
T Add(const T& t1, const T& t2)
{
	cout << "T Add(const T& t1, const T& t2)" << endl;
	return t1 + t2;
}
template<typename T1,class T2>
auto Add(const T1& t1, const T2& t2)
{
	cout << "auto Add(const T1& t1, const T2& t2)" << endl;
	return t1 + t2;
}
int main()
{
	int a1 = 0,a2=9;
	double b1 = 3.3,b2=9.3;
	Add(a1, a2);
	Add(b2, b1);
	Add(a1, b1);
	return 0;
}

在这里插入图片描述
因为模版并不是创建了这个函数,所以模版间是可以同时存在的
这个我们可以看出,函数调用是调用最适合的,同时为int时,因为有现成的,所以就调用这个
同时为double时,调用第二个,第一个也可以调用,但是不适合,因为会发生隐式类型转换
调用第三个也不是最合适的,因为是两个相同的,那就调用相同的就可以了啊
第三个,一个为int,一个为double,那就调用第三个最合适了

int main()
{
	int a1 = 0,a2=9;
	double b1 = 3.3,b2=9.3;
	Add<int,int>(a1, b1);
	Add<int>(b1, a1);
	Add<double>(b1, a1);
	return 0;
}

在这里插入图片描述
可以看出,多个参数的显示实例化,也就是<int,int>了,这个表示将T1,T2都弄为int,因为显示实例化的两个,所以调用第三个
Add(b1, a1);这个嘛,T Add(const T& t1, const T& t2)中的T就直接相当于变为了int,T1变为int,T2未知,这样的话,b1肯定要强制类型转换为int,那么都为int,选第二个呗
实例化就是指定那个T为什么,指定顺序与定义T的顺序一致

3.类模板

所谓类模板,就是对类创建一个模版

class Stack
{
public:
	void Push(int x)
	{
		/
	}
private:
	int* _a;
	int _size;
	int _capacity;
};

如果不是模版的话就是这样的,现在直接变成模版

template<class T>
class Stack
{
public:
	void Push(T x)
	{
		/
	}
private:
	T* _a;
	T _size;
	T _capacity;
};

int main()
{
	Stack<int> s1;
	Stack<double> s2;
	return 0;
}

这个就相当于模版了,只不过调用模版的时候一定要显示实例化,因为这个不像函数,可以根据参数来得出T的类型,当然如果函数也不能根据参数类型来得出T,也只能显示实例化了

4.STL简介

STL叫做标准模板库,里面主要包括数据结构与算法,还包括一些什么内存池,仿函数,迭代器,配接器之类的东西
反正STL很重要

总结

这一节比较简单,主要是给STL开个头,下一节我们讲string,也就是串

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值