天天看点

C++函数模板与类模板函数模板类模板

目录

  • 函数模板
  • 类模板

函数模板

在编写程序时有时候我们需要编写大量的重复的代码,如写一个实现交换的函数,结构其实很简单,但是实际中需要些不止一个函数来实现,因为对于不同的类型如int、double等需要不同的函数,即使使用函数重载也只是解决了函数名的问题,各类型调用时可以使用同一个函数名,但是函数却还是要写好几份,于是为了解决这一问题C++定义了函数模板

使用格式:

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

//例:
template<typename T>
void Swap(T& left, T& right)//函数内T未知类型,取决于出入参数的类型
{
	T temp = left;
	left = right;
	right = temp;
}

           

模板函数很好的解决了这一问题,这里只是定义了函数的模板,并没有显示定义一个函数,就相当于定义了一个类,但是没有定义对象。在调用到该函数时,编译器根据传入的参数生成对应的函数。

C++函数模板与类模板函数模板类模板

不同类型使用函数模板

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

该函数都是"T"类型的,对这个函数进行调用时,要传入两个类型相同的参数,在实际中,有时候有两个不同类型的变量需要使用这个函数。这时候有两个方法。

  • 隐士类型转换
int a1 = 10, a2 = 20;
	double d1 = 10.0, d2 = 20.0;
	Add(a, (int)d);
           

将double型强转为int型,然后调用函数。

  • 显示类型转换
int a1 = 10, a2 = 20;
	double d1 = 10.0, d2 = 20.0;
	Add<int>(a, d);
           

指定调用函数是类型为int型

匹配优先级

// 专门处理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版本
}
           

显示定义的函数与模板函数共存时,编译器优先调用显示定义的函数而不是模板函数。

类模板

C++不仅有模板函数,也有类模板

格式

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

例:

// 动态顺序表
// 注意:Vector不是具体的类,是编译器根据被实例化的类型生成具体类的模具
template<class T>
class Vector
{
public:
	Vector(size_t capacity = 10)
		: _pData(new T[capacity])
		, _size(0)
		, _capacity(capacity)
	{}
	// 使用析构函数演示:在类中声明,在类外定义。
	~Vector();
	void PushBack(const T& data);
		void PopBack();
		// ...
		size_t Size() { return _size; }
	T& operator[](size_t pos)
	{
		assert(pos < _size);
		return _pData[pos];
	}
private:
	T* _pData;
	size_t _size;
	size_t _capacity;
};
// 注意:类模板中函数放在类外进行定义时,需要加模板参数列表
template <class T>
Vector<T>::~Vector()
{
	if (_pData)
		delete[] _pData;
	_size = _capacity = 0;
}
           

这里就是定义了一个类模板,类中的类型都是T类型,在定义对象时指定类型,便可以定义不同类型的对象了

定义类

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

// Vector类名,Vector<int>才是类型
Vector<int> s1;
Vector<double> s2;
           

合理使用模板可以大大提高程序效率

继续阅读