C++模板初阶

1.函数模板

为什么有模板C++要引入模板?? 

如果我们要实现一个交换函数,比如

#include<iostream>
#include<string>
using namespace std;
void swap(int& A, int& B)
{
	int temp = A;
	A = B;
	B = temp;
}
int main()
{
	int a = 10;
	int b = 20;
	swap(a, b);
	cout << a << " " << b << endl;
	return 0;
}

那么当我要同时进行 double类型 ,float类型,int类型等各种类型之间的转换

和不同类型之间的转换,那么我们是不是要写很多代码  ??

比如

#include<string>
using namespace std;
void swap(float& A, float& B)
{
	int temp = A;
	A = B;
	B = temp;
}
void swap(double& A, double& B)
{
	int temp = A;
	A = B;
	B = temp;
}
void swap(int& A, int& B)
{
	int temp = A;
	A = B;
	B = temp;
}
int main()
{
	double c = 60.4;
	double d = 50.3;
	float e = 40.2;
	float f = 30.1;
	int a = 10;
	int b = 20;
	swap(a, b);
	swap(c, d);
	swap(e, f);
	cout << e << " " << f << endl;
	cout << c << " " << d << endl;
	cout << a << " " << b << endl;
	return 0;
}

那么有没有什么办法,让我写一个函数就够用呢??? 

 

C++为我们提供了一个模板

 我们只要写一个函数,那么这个函数的形参类型会随着我们给的实参类型而变化

我们给什么实参类型,这个形参就变成什么。

那么这样是不是就方便了很多

模板的格式

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

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

上述class可以用typename代替

#include<iostream>
#include<string>
using namespace std;
template<class T>
void Swap(T& A, T& B)
{
	T temp = A;
	A = B;
	B = temp;
}
int main()
{
	double c = 60.4;
	double d = 50.3;
	float e = 40.2;
	float f = 30.1;
	int a = 10;
	int b = 20;
	Swap(a, b);
	swap(c, d);
	swap(e, f);
	cout << e << " " << f << endl;
	cout << c << " " << d << endl;
	cout << a << " " << b << endl;
	return 0;
}

 根据结果我们可以判断出,我们只构造了一个函数,但可以进行多个类型的初始化 

 

 编译器通过模板,在程序进行时根据情况通过这个模板来构建几个不同的函数

那我们可不可以将两个不同类型的数据进行交换呢

我们可以看到,当我们将int类型数据和float类型数据进行交换时编译器会报错。 

void Swap(T& A, T& B)
{
	T temp = A;
	A = B;
	B = temp;
}

如上图,这是因为当我们传第一个实参时,T就识别到了实参的类型,那么T就会转化为这个实参的类型,之后在这个函数中这个T就会一直是这个类型,所以传第二个参数时会报错。

那么我们要怎么解决这个问题呢??
我们可以使用两个模板类型来解决这个问题

#include<iostream>
#include<string>
using namespace std;
template<class T,class P>
void Swap(T& A, P& B)
{
	T temp = A;
	A = B;
	B = temp;
}
int main()
{
	double c = 60.4;
	double d = 50.3;
	float e = 40.2;
	float f = 30.1;
	int a = 10;
	int b = 20;
	Swap(a, f);
	cout << a << " " << f << endl;
	return 0;
}

运行结果

 

我们可以看到,当我交换a和f的数据时,发生了类型转换,30.1变为了30。

我们除此之外我们还可以用别的方法来进行交换,比如

强制转换类型

#include<iostream>
#include<string>
using namespace std;
template<class Y>
Y Add(const Y& a, const Y& b)
{
	return a + b;
}
int main()
{
	float f = 30.1;
	int a = 10;
	cout << Add(a, (int)f) << endl;
	cout << a << " " << f << endl;
	return 0;
}

 

 其中f的类型转化为了int。

但是我们需要注意,这个f在被转化为int时,是一个临时变量,它将它这个值转递过去时,是一个临时变量,我们需要用const来接收这个临时变量。 

 显示实例化也可以解决上面的问题

我们用这个模板来实例化一个函数’

比如

#include<iostream>
#include<string>
using namespace std;
template<class Y>
Y Add(const Y& a, const Y& b)
{
	return a + b;
}
int main()
{
	float f = 30.1;
	int a = 10;
	cout << Add<int>(a, f) << endl;
	cout << a << " " << f << endl;
	return 0;
}

 

显示实例化就是在函数名和()中间加一个<类型名>来将里面的参数强制转化为想要的类型 

模板函数匹配原则

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

#include<iostream>
#include<string>
using namespace std;
template<class Y>
Y Add(const Y& a, const Y& b)
{
	return a + b;
}
int Add(const int& a, const int & b)
{
	return a + b;
}
int main()
{
	float f = 30.1;
	int a = 10;
	cout << Add<int>(a, f) << endl;
	cout << a << " " << f << endl;
	return 0;
}

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

2.类模板 

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

class 类模板名

{

// 类内成员定义

};

#include<iostream>
#include<string>
using namespace std;
template<class T>
class Stack
{
public:
	Stack(int n = 4)
	{
		arr = new T[4];
		size = 0;
		capacity = n;
	}
	void pop()
	{
		size--;
	}
	void push(T date)
	{
		if (size == capacity)
		{
			T*temp = new T[capacity * 2];
			memcpy(temp, arr, capacity * 2);
			delete arr;
			arr = temp;
			capacity = capacity * 2;
		}
		arr[size] = date;
		size++;

	}
	void print()
	{
		for (int i = 0; i < size; i++)
		{
			cout << arr[i] << endl;
		}
	}
private:
	T* arr;
	int size;
	int capacity;
};
int main()
{
	Stack<int> ST(10);
	ST.push(10);
	ST.push(20);
	ST.push(30);
	ST.push(40);
	ST.push(50);
	ST.pop();
	ST.pop();
	ST.pop();

	ST.print();

}

类模板实例化

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

 / / Stack是类名,Stack<int>才是类型

Stack<int> st1; // int

Stack<double> st2; // double

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值