C++初识模板以及模板编程

模板

我们知道,如果要用一个交换函数,那么要交换int型的两个数,就需要写一个int类型的交换函数,如果交换char类型的两个字符,就需要写一个char类型的交换函数。这样会造成代码的复用率低,虽然函数重载可以实现,但是函数的复用率仍然很低,且如果一个出错,那可能所有重载都会出错,为了解决这一问题,C++中引入了模板这一概念。
首先需要了解一下泛型编程的概念:
编写与类型无关的通用代码,是代码复用的一种手段。模板是泛型编程的基础。

函数模板

函数模板:
函数模板代表了一个函数家族,该函数模板与类型无关,在使用时被参数化,根据实参类型产生函数的特定 类型版本。
函数模板格式:
template
比如交换函数我们可以写成
隐式实例化:编译器自己会去匹配类型

template<class type>
void swap(type& left,type& right)
{
	type tmp = left;
	left = right;
	right = tmp;
}

这样,每次调用swap函数时,编译器会根据参数类型,自动确定类型,并进行交换。
注意:
函数模板是一个蓝图,它本身并不是函数,是编译器用使用方式产生特定具体类型函数的模具。所以其实模 板就是将本来应该我们做的重复的事情交给了编译器
在编译器编译阶段,对于模板函数的使用,编译器需要根据传入的实参类型来推演生成对应类型的函数以供 调用。比如:当用double类型使用函数模板时,编译器通过对实参类型的推演,将T确定为double类型,然 后产生一份专门处理double类型的代码,对于字符类型也是如此。

但是下面这样使用是不对的:

template<class type>
void swap(type& left,type& right)
{
	type tmp = left;
	left = right;
	right = tmp;
}
int main()
{
	int a = 10;
	char b = 'a';
	swap(a,b);
}

因为编译器无法断定到底是int类型还是char类型
因此模板函数需要写成这样

template<class type,class> type2>
void swap(type& left,type2& right)
{
	type tmp = left;
	left = right;
	right = tmp;
}

显示实例化:在函数名后的<>中指定模板参数的实际类型

template<class T>
T add(T& a,T& b)
{
  return a + b;
}
void test()
{
	int a = 10;
	double b = 20.5;
	add<int>(a,b);//显式实例化成int类型
}

模板函数匹配原则

1.普通函数与模板函数共存时,如果普通函数的参数类型可以完全匹配,则执行普通函数,不进行模板函数的实例化。
2.普通函数与模板函数共存时,普通函数的参数类型不能完全匹配,但是实例化的函数可以完全匹配参数类型,则进行实例化。
3.普通函数与模板函数共存时,但是指定了需要实例化,则进行实例化。

类模板

格式如下:

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

例如:

template<class T1,class T2,class T3>
class date
{
public:
	date(T1 year,T2 month,T3 day)
		:_year(year)
		,_month(month)
		,_day(day)
		{}
private:
	T1 _year;
	T2 _month;
	T3 _day;
};

如果在类外定义类模板的成员函数,则需要加上泛性申明以及作用域(类名+<泛性参数>)。

template<class T1,class T2,classT3>
void date<T1,T2,T3>::display()
{
	cout<<_year<<" "<<_month<<' '<<_day<<endl;
}

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

你可能感兴趣的:(C++,c++)