函数模板(template关键字的应用)

注释:本文主要介绍了函数模板的由来以及用法,还有关键字template。
我们感到时间的延续像一条我们无法逆行的小溪。
——柏格森
函数模板(template关键字的应用)_第1张图片

文章目录

  • 一、语言的定式
  • 二、函数模板
    • 2.1 函数模板格式
    • 2.2 模板函数的实例化
      • 2.2.1隐式实例化/显式实例化
    • 2.3 模板参数的匹配原则
  • 三、类模板!
    • 3.1 类模板普遍格式
    • 3.2 类模板的实例化


一、语言的定式

生活中大多数产品都是制式的,都或多或少有他们各自的磨具用以加快产品的生产,但是我们发现之前在C语言中函数几乎是确定的除非我们改变函数本身的生命,类型与类型之前也不是互通的,这个时候如果想要实现不同类型变量之前的计算/交换等就要书写非常多冗余的函数。非常的不方便就拿一个Add函数来举例吧。

//两个int类相加
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

这仅仅只是三种同类型数据的Add函数,会让我们的代码量指数上升。
有多少种类型就会有多少种Add,一旦不符合就会报错。
当然我们还可以使用函数重载来减少他们的数量,但是这还只是普通类型,还没有加入const类变量还没有加入其他的各种运算/判断等。
这时我们就需要有一个好像磨具一样的东西来只传输我们的参数,然后得到我们的结果。在C++中自然就引入了这个东西我们称之为模板

二、函数模板

函数模板代表的是一个函数类他与传入的类型无关,在使用的时候被参数化,根据实参类型产生函数的特定类型版本。

2.1 函数模板格式

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

 1.template
 void Swap( T& left, T& right)
 {
 T temp = left;
 left = right;
 right = temp;
 }

注意:typename是用来定义模板参数关键字,也可以使用class。(切记:不能使用struct代替class)

函数模板是一个蓝图,它本身并不是函数,是编译器用使用方式产生特定具体类型函数的模具。所以其实模板就是将本来应该我们做的重复的事情交给了编译器。
它的底层也是编译器去通过模板生成对应的函数,并非C++ 引入了一种新的定义,是一种语法糖。

2.2 模板函数的实例化

当不同的类型的参数使用函数模板的时候,首先要进行函数的实例化。

2.2.1隐式实例化/显式实例化

//函数实例化
template
T Add(const T& left, const T& right)
{
return left + right;
}
//隐式实例化
int main(){
int a1 = 10, a2 = 20;
double d1 = 10.0, d2 = 20.0;
//函数传输的时候不进行类型署名,让编译器自己识别。
//下第一天编译就会报错,当我们把a1识别转化为时,a2就会判定为double性不能进行相加,因为我们仅仅定义了一个T
Add(a1, a2);
Add(d1, d2);
}
//显式实例化
int main(void)
{
int a = 10;
double b = 20.0;
//直接进行强制转化,指定结果类型
Add(a, b);
return 0;
}
//同时我们还可以直接进行类型转换比如
Add(a, (int)d);

2.3 模板参数的匹配原则

!一个模板参数可以和一个同名函数同时存在。

// 专门处理int的加法函数
int Add(int left, int right)
{
return left + right;
}
// 通用加法函数
template
T Add(T left, T right)
{
return left + right;
}
void Test()
{
Add(1, 2); // 与非模板函数匹配,编译器不需要特化
Add(1, 2); // 调用编译器特化的Add版本
}

编译器是聪明的,当非模板函数和同名函数模板,如果其他条件都相同,在调动时会优先调用非模板函数而不会从该模板产生出一个实例。如果模板可以产生一个具有更好匹配的函数, 那么将选择模板。
就好像我们定义非模板函数与我们需要处理的数据在类型上完全一致,这时候编译器就会只能选择我们所定义的非模板函数。

三、类模板!

C++相对于C改变最大的一个方向就是函数类,在进行大的项目制作时,编程人员的思路往往是大相径庭的,这时候类模板的出现就弥补了很多。

3.1 类模板普遍格式

templete 
class zyl{
public:
	zyl(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 
zyl::~zyl()
{
	if(_pData)
	delete[] _pData;
	_size = _capacity = 0;
}

3.2 类模板的实例化

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

// Vector类名,Vector才是类型
Vector s1;
Vector s2;

你可能感兴趣的:(c++,算法,开发语言)