模板
- 模板是C++的一种特性,允许函数或类(对象),通过泛型的形式表现或运行
- 模板可以使函数或类在对应不同的型别的时候正常工作,无需为每一个型别都写一份代码
两种模板
- 类模板:使用泛型参数的类
- 函数模板:使用泛型参数的函数
模板实例化
- 模板的声明其实并未给出一个函数或类的完全定义,只是提供了一个函数或类的语法框架
- 实例化是从模板构建出一个真正的函数或类的过程
有两种类型:
显示实例化:在代码中明确指定要针对哪种类型进行s实例化
隐式实例化:在首次使用时根据具体情况使用一种合适的型别进行实例化
add <int>(1+2);//隐式
add<char>('a','b')//显式
函数模板
- 函数模板是参数化的一族函数
- 通过函数模板,可以定义一系列函数,这些函数都基于同一套代码,但是可以作用在不同型别的参数上
例子
template <typename T> //模板的定义
T add( T a, T b) //模板的定义必须要和函数模板在一起
{
printf("%d\n",a + b);
return a + b;
} //定义了add函数模板,其中传参为T,返回值为T
int main()
{
int a = 2, b = 2;
printf("pri a+b:%d\n", add(a,b));
printf("pri char:%d\n",add('b', 'a'));
std::cout << "Hello World!\n";
}
对于不同的型别,都从模板实例出不同的形体
我们对他进行两次调用,分别进行不同的传参,他就有不同的表现形式,比如传入是int,就是int,传入char就是char
实例化:用具体的型别代替模板参数T的过程就叫实例化,从而产生一个模板实例
结论
模板被编译了两次
- 没有实例化之前,检查模板代码本身是否有语法错误
- 实例化期间,检查模板的调用是否合法
参数推导
- 模板参数是有传递给模板函数的实参决定的
- 不允许自动类型转换,每个T必须严格匹配
add (1,2);//yes
add (1,2.3);//error
add ('a',2);//error
函数模板重载
- 函数模板也可以像普通函数一样重载
- 非模板函数可以和同名模板函数共存
- 编译器通过函数模板参数推导来决定使用调用哪个重载
template <typename T,typename T_1>
T_1 add( T a, T b)
{
printf("mode one %d\n",a + b);
return a + b;
}
template <typename T>
void add(T a, T b)
{
printf("mode two %d\n", a + b);
cout << ::a + b << endl;
}
void add(int a, int b)
{
cout << "你真好" << endl;
}
int main()
{
int a = 2, b = 2;
add(1, 2); //优先调用函数
add<int>(1, 2); //调用函数模板需要显示调用
add<int,int>(1,2)//有返回值的函数模板需要显式调用
总结
- 对于不同的实参型别,函数模板定义了一组函数
- 当传递模板实参的时候,函数模板依据实参的型别进行实例化
- 可以显式指定模板实参型别
- 函数模板可以重载
- 当重载函数模板的时候,将改变限制在:显示指定模板参数