在C++中,有一个用起来感觉很爽的功能,那就是模版,顾名思义,就是提供一个图纸,让编译器制动生成某个东西,可以很方便的达到我们的某些需求(例如,实现一个加法函数,可以避免开发者写很多个重载函数)。
C++中,模版可以分为两类:“函数模版”,“类模版”。
一、函数模版
函数模版的基本格式如下:
template<class Template>
Template Func(Template a, Template b)
{
return a + b;
关键字“template”+“<>”,其中,“<>”中写的是关键字“class”或者“typename”,后面紧跟模版的类型名字即上述代码中的“Template”,这个取名可以是任意的,它代表的是类型。
编译器可以自己识别输入的参数类型,从而将“Template”转换成相应的类型,如以下示例:
#include<iostream>
using namespace std;
template<class Template>
Template Func(Template a, Template b)
{
return a + b;
}
int main()
{
cout << Func(1, 2) << endl;
cout << Func(1.1, 2.1) << endl;
return 0;
}
通过两种类型不同的示例可以大致了解模版在函数中的用处,那么它的运行结果如下:
上述只定义了一个模版参数,那么我可以用一个模版参数来代表两个不同的类型吗?比如:
#include<iostream>
using namespace std;
template<class Template>
Template Func(Template a, Template b)
{
return a + b;
}
int main()
{
cout << Func(1, 2.1) << endl;
return 0;
}
答案是否定的。会出现报错。从本质上来说,编译器在已经确定了一个模版参数的类型之后是不会进行类型转换的,倘若真想输入两个不同类型的变量,那么在增加一个模版参数即可:
#include<iostream>
using namespace std;
template<class Template1 , class Template2>
Template1 Func(Template1 a, Template2 b)
{
return a + b;
}
int main()
{
cout << Func(1, 2.1) << endl;
return 0;
}
或者显式地标明输入参数的类型。
二、模版实例化
模版和类一样,只是个图纸,它也是可以被实例化出来的。用不同类型的参数使用函数模板时,称为函数模板的实例化,它分为显式实例化和隐式实例化。
在上述例程中,通过编译器自己判断出来的模版参数的类型称为“隐式实例化”,通过开发者指定类型称为显式实例化:
#include<iostream>
using namespace std;
template<class Template>
Template Func(Template a, Template b)
{
return a + b;
}
int main()
{
cout << Func<int>(1, 2.1) << endl;//显式实例化
return 0;
}
通过在调用模版函数的时候,在函数名后加上“<指定类型>”,即可完成显式实例化代表着函数参数是我们指定类型的变量运行结果如下:
另外,当出现模版函数和其他函数同名同参数个数,那么编译器会优先采用非模版函数。
三、类模版
类模板和函数模版类似,不同的地方在于类模版在实例化的时候,需要在类名之后指定模版的类型,即显式实例化,这个操作是必须的,无论是否在类模版中使用了类模版中定义的变量(即:template<class Template>中的“Template”):
#include<iostream>
using namespace std;
template<class Template>
class Test
{
public:
Test(int a = 1)
:_test(a)
{}
private:
int _test;
};
int main()
{
Test<int> mytest;
Test<double> mytest1;
Test<char> mytest2;
return 0;
}