模板:
泛型编程:用一个标志来表示类型,不是实际的类型。独立于任何特定类型的编程,c++的一个部分。
C++提供两种模板:函数模板和类模板。
函数模板:
作用:建立通用函数,其函数返回值类型和形参类型可以不具体制定,用一个虚拟的类型代表。
格式:template<class T1,typename T2>
返回值 函数名(参数){ }
解释: template ----- 声明创建模板
typename ----- (也可以用class代替)表明后的类型是一个通用类型,或许叫做虚拟类型
T1-------------- 通用类型或者虚拟类型,可以在函数中直接当做普通类型使用。
函数模板的调用:
第一种:函数名 <实际类型1,实际类型2>(参数列表);
显式类型推导 fun<int>(1,2);
第二种:函数名(参数);
隐形类型推导
注意:显示类型推导 参数和推导的类型必须一致。
如果有普通函数和模板函数,在调用时可以用显示调用,省略类型的方式 swap<>(1,2)。
实例:
#include <iostream>
using namespace std;
//两个整型交换函数
void swapint(int& a, int& b)
{
int temp = a;
a = b;
b = temp;
}
//两个浮点型数据交换函数
void swapdouble(double& a, double& b)
{
double temp = a;
a = b;
b = temp;
}
void test1()
{
int a = 10;
int b = 20;
swapint(a, b);
cout << "a=" << a << endl;
cout << "b=" << b << endl;
double c = 1.1;
double d = 2.2;
swapdouble(c, d);
cout << "c=" << c << endl;
cout << "d=" << d << endl;
}
//函数模板
template<typename T>//声明一个模板,提供一个通用的数据类型T
void myswap(T& a, T& b)
{
T temp = a;
a = b;
b = temp;
}
void test2()
{
int a = 10;
int b = 20;
//利用函数模板交换
//两种方式使用函数模板
//1.自动类型推导
//myswap(a, b);//隐式推导
//myswap<int>(a, b);//显式推导
cout << "a=" << a << endl;
cout << "b=" << b << endl;
double c = 1.1;
double d = 2.2;
cout << "c=" << c << endl;
cout << "d=" << d << endl;
}
int main(){
void test1();
void test2();
system("pause");
return 0;
}
普通函数和函数模板的区别:
(1) 函数只可以有一种数据类型相匹配。模板有多种类型
(2) 隐式推导优先使用普通函数,只有普通函数不匹配才使用函数模板
(3)函数模板只有在调用时,才会构建函数,而普通函数是在编译时。
(4)普通函数调用时候可以发生自动类型转换,而函数模板不行。
//普通函数
int myadd(int a, int b)
{
return a + b;
}
void test1()
{
int a = 10;
int b = 20;
int c = 'c';
cout <<myadd(a,b) << endl;
cout << myadd(a, c) << endl;//自动将字符转化成整数
}
//函数模板
template<class T>
T myadd2(T a, T b)
{
return a + b;
}
void test2()
{
int a = 10;
int b = 20;
char c = 'c';
//自动类型推导,不发生隐式类型转换
cout << myadd2(a, b) << endl;
//cout << myadd2(a, c) << endl;//无法自动转换
//显示指定类型
cout << myadd2<int>(a, c) << endl;
}
普通函数与函数模板的调用规则:
(1).如果函数模板和普通函数都可以实现,优先调用普通函数。
(2).可以通过空模板参数列表来强制调用函数模板。
(3).函数模板也可以发生重载。
(4).如果函数模板可以产生更好的匹配,优先调用函数模板。
模板的局限性:
某些特殊数据类型不能直接使用模板进行运算,需要进行实例化对其特殊运算。
函数模板重载:
和普通函数的重载相似。也是同一个作用域类函数名相同参数列表不同。
参数顺序不同的重载:
template <class T1,class T2>void swap1(T2 a,T1 b)
template <class T1,class T2>void swap1(T1 a,T2 b)
参数个数不同的重载:
template <class T1,class T2> void swap1(T1 a,T2 b)
template <typename T2> void swap1(T2 t)
传入不同的参数,调用不同的版本
注意
在函数参数顺序不同的重载中,实例化的时候不可以是相同类型
例如 swap1<int ,int >(1,2)则没法匹配哪个函数。