在代码编写过程中,有时我们会遇到一些问题,他们有相同或者类似的格式。
比如我要编写一个通用的加法函数,针对不同的参数和返回类型需要编写各种函数,比如如下两种:
int Add(int a, int b)
{
return a + b;
}
char Add(char a, char b)
{
return a + b;
}
这两种分别是针对int和char参数的加法函数,如果我需要float和double就需要在添加两个函数,而且函数大体是和如上函数相同的,只是函数返回类型和参数类型不同,这样不停的重写使其重载会浪费很多的时间和精力,所以我们就需要了解模板和泛型编程的好处。
首先我们先了解什么是模板:函数模板代表了一个函数家族,该函数与类型无关,在使用时被参数化,根据实参类型特定类型版本。
也就是说我们首先创造出一个函数模板,他不会固定函数的返回类型和参数类型,他会在我们给定参数时决定写出那种类型的函数,这样对于我们编程就非常的方便了。
template就是定义模板的关键字。
接下来为template的使用方式,比如我现在要学出一个通用的加法,可以综合上述所有类型的Add函数:
template<class N>//这里的class可以用typename代替
N Add(const N& a,const N& b)
{
return a + b;
}
这就是一个简易的通用加法函数,我们来运行函数看看结果:
int main()
{
cout << Add(4, 5)<<endl;
cout << Add('1', '2') << endl;
getchar();
return 0;
}
如图为我函数的执行结果,可以看出两种方式都能运行。
对于函数模板,参数可以任意设定,返回类型也一样,不一定要一样,比如如下代码:
T Add(const N& a, const T& b)
{
return a + b;
}
这里我定义了两种类型,返回类型为其中之一,这样就可以对两种类型不一样的数据进行加法。
而对于函数模板也可以存在已确定的参数,成为非模板类型参数,比如如下代码,数组大小就是已知的int类型:
template<class N,int T>
void Funtest(N(&arry)[T])
{
for (int i = 0; i < T; i++)
{
arry[i] = i;
}
}
int main()
{
int a[5];
Funtest(a);
return 0;
因为模板函数在编译阶段是不会形成具体函数,所以如果在代码中存在需要用到的准确类型的函数就不会重新生成对应函数了。如下代码:
template<class N>
N Add(const N& a,const N& b)
{
return a + b;
}
int Add(int a, int b)
{
return a + b;
}
int main()
{
cout<<Add(1, 2);
getchar();
return 0;
}
在这里就会直接调用已编写好的函数,不会调用模板函数。
但是如果仍然想调用模板函数的话可以改为如下格式:
template<class N>
N Add(const N& a,const N& b)
{
return a + b;
}
int Add(int a, int b)
{
return a + b;
}
int main()
{
cout<<Add<int>(1, 2);
getchar();
return 0;
}
这样就会调用模板函数去生成函数了。