简单使用C++模板

在C++中,函数模板是一种参数化的工具,可以用来创建一个通用的函数,可以处理多种不同的数据类型。

泛型编程是通过编写与类型无关的通用代码,来实现代码复用。因此,C++设置了模板以实现编写与类型无关的通用代码,从而实现代码复用。

在C++中,模板分为函数模板和类模板两种。模板通过使用 template 关键字声明

函数模板

函数模板与类型无关,只有在使用时才会根据实参类型产生特定的函数。

函数模板的格式为:

template<typename T1, typename T2, ..., typename Tn>
返回类型 函数名(参数列表) 
{
	// 函数体
}


//或者也可以用class

template<class T1, class T2, ..., class Tn>
返回类型 函数名(参数列表)
{
	// 函数体
}

具体代码演示:

template<class T>
void Swap(T& p1, T& p2)
{
	T tmp = p1;
	p1 = p2;
	p2 = tmp;
}

参数模板的实例化

与类的实例化类似,用不同类型的参数使用函数模板就成为函数模板的实例化。在函数模板的实例化中,又分为隐式实例化和显示实例化。

隐式实例化又成为推导实例化,即让编译器根据实参自动推导具体类型。

显示实例化即要手动指定具体类型。

代码示例:

#include<iostream>
using namespace std;

template<class T>
void Swap(T& p1, T& p2)
{
	T tmp = p1;
	p1 = p2;
	p2 = tmp;
}

int main()
{
	int a = 11, b = 22;
	double m = 3.6, n = 9.6;

	//隐式实例化
	cout << "a=" << a << " b=" << b << endl;
	Swap(a, b);			  
	cout << "a=" << a << " b = " << b << endl;
						  
	cout << "m=" << m << " n=" << n << endl;
	Swap(m, n);			  
	cout << "m=" << m << " n=" << n << endl;

	return 0;
}
#include<iostream>
using namespace std;

template<class T>
T Add(const T& p1, const T& p2)
{
	return p1 + p2;
}

int main()
{
	int a1 = 10, a2 = 20;
	double b1 = 3.6, b2 = 8.8;

	//隐式实例化
	cout << Add(a1, a2) << endl;
	cout << Add(b1, b2) << endl;

	return 0;
}

如果实参类型多样,那编译器不能自动识别出类型。

所以就需要手动指定(也就是显示实例化)。显式实例化需要在模板名字后跟<>,然后将实例化的类型放在<>中即可。

#include<iostream>
using namespace std;

template<class T>
T Add(const T& p1, const T& p2)
{
	return p1 + p2;
}

int main()
{
	int a1 = 10, a2 = 20;
	double b1 = 3.6, b2 = 8.8;

	//隐式实例化
	cout << Add(a1, a2) << endl;
	cout << Add(b1, b2) << endl;

	//显示实例化
	cout << Add<int>(a1, b1) << endl;
	cout << Add<double>(a1, b1) << endl;

	return 0;
}

这个函数还可以直接进行类型强转。

#include<iostream>
using namespace std;

template<class T>
T Add(const T& p1, const T& p2)
{
	return p1 + p2;
}

int main()
{
	int a1 = 10, a2 = 20;
	double b1 = 3.6, b2 = 8.8;

	//隐式实例化
	cout << Add(a1, a2) << endl;
	cout << Add(b1, b2) << endl;

	//类型强转
	cout << Add(a1, (int)b1) << endl;
	cout << Add((double)a1, b1) << endl;

	return 0;
}

参数模板的匹配规则

当一个非模板的函数和一个同名的函数模板同时存在时,如果其他条件都相同,编译器会优先调用

非函数模板,不会再从模板中实例化一个出来。但如果模板能产生更匹配的函数,则会使用模板。

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

#include<iostream>
using namespace std;

template<class T1, class T2>
T1 Add(const T1& p1, const T2& p2)
{
	cout << "模板" << endl;
	return p1 + p2;
}

int Add(int p1, int p2)
{
	cout << "非模板" << endl;
	return p1 + p2;
}

int main()
{
	Add(1, 2);
	Add(1, 8.8);

	return 0;
}

类模板

类模板的格式为:

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

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

#include<iostream>
using namespace std;

template<class T>
class Stack
{
public:
	Stack(int n = 4)
		:arr(new T[n])
		,size(0)
		,capacity(n)
	{

	}

	void Push(const T& x)
	{
		if (capacity == size)
		{
			T* tmp = new T[capacity * 2];
			memcpy(tmp, arr, sizeof(T) * size);
			delete[] arr;
			arr = tmp;
			capacity *= 2;
		}
		arr[size++] = x;
	}

	~Stack()
	{
		delete[] arr;
		arr = nullptr;
		capacity = size = 0;
	}

private:
	T* arr;
	int size;
	int capacity;
};

int main()
{
	//类模板只能显式实例化
	Stack<int> st;

	st.Push(1);
	st.Push(2);
	st.Push(3);
	st.Push(4);

	return 0;
}

在模板类中要想把类中的函数写到类外,就不只是指定类域那么简单。

因为模板类不是真正的类,要写到类外,就要重新写类模板,并在类模板名后加上<>,并在其中写入类类型。

#include<iostream>
using namespace std;

template<class T>
class Stack
{
public:
	Stack(int n = 4)
		:arr(new T[n])
		,size(0)
		,capacity(n)
	{

	}

	void Push(const T& x);

	~Stack()
	{
		delete[] arr;
		arr = nullptr;
		capacity = size = 0;
	}

private:
	T* arr;
	int size;
	int capacity;
};

template<class T>
void Stack<T>::Push(const T& x)
{
	if (capacity == size)
	{
		T* tmp = new T[capacity * 2];
		memcpy(tmp, arr, sizeof(T) * size);
		delete[] arr;
		arr = tmp;
		capacity *= 2;
	}
	arr[size++] = x;
}

int main()
{
	//类模板只能显式实例化
	Stack<int> st;

	st.Push(1);
	st.Push(2);
	st.Push(3);
	st.Push(4);

	return 0;
}

并且,类模版不建议声明和定义分离到两个文件(.h 和.cpp),会出现链接错误。

小结

因为swap函数会经常使用,所以C++直接提供了swap这个函数模板,可供我们使用。

#include<iostream>
using namespace std;

int main()
{
	int a = 10, b = 20;
	swap(a, b);
	cout << a << ' ' << b << endl;

	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值