C++模板入门教程(一)——模板概念与基本语法

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

C++模板⼊门教程(⼀)——模板概念与基本语法
前⾔
有些⼈提到C++模板就会下意识地觉得可怕、看不懂、避⽽远之。

其实模板并不复杂,⽽且熟练后可以⽤在⽇常⼯作中,可以帮助我们重⽤代码,让代码更简洁、易读、可维护。

希望这个系列的⽂章,能够让更多⼈发现模板的魅⼒,帮助⼤家写出更⾼质量的代码。

我们为什么需要模板
我们有时候会遇到这样的情况:同样的函数,我们要为不同的类型写不同的版本,内容与逻辑都是⼀摸⼀样的,只有他们的类型不⼀样。

⽐如我们写⼀个max函数,传⼊两个数字,返回⼤的数字。

很⾃然地,两个参数的类型和返回的类型必须是相同的。

如果不使⽤模板,我们需要使⽤函数重载,为不同的类型写不同的函数:
int max(int a, int b)
{
return a < b ? b : a;
}
float max(float a, float b)
{
return a < b ? b : a;
}
这⾥我只写了2个函数,实际上short, long, unsigned, double等等类型都需要专门的max函数,结果就是需要写⼗⼏个⼏乎⼀摸⼀样的代码。

如果函数功能更复杂⼀些,函数实现需要更多⾏,就会出现⼤量冗余重复的代码,⽽且不容易维护,很容易出错。

这个时候如果我们能够根据特定的模板批量⽣成⼀系列代码,将会⽅便很多。

为此,我们可以使⽤C++中的模板
什么是模板
顾名思义,模板就是编译器⽣成代码⽤的模⼦。

模板有两类,函数模板和类模板(C++14开始出现了变量模板,不过不在此讨论)。

如果想要⽣成函数代码,则需要⽤函数模板,如果想要⽣成类定义,则需要⽤到类模板。

这篇⽂章会先介绍函数模板,下篇⽂章再介绍类模板。

函数模板
我们可以为上⾯的⼀系列max函数写⼀个函数模板。

template<typename T>
T max(T a, T b)
{
return a < b ? b : a;
}
我们暂时不细说语法,先看⼀看⼤致的样⼦,其实函数模板的长相和普通的函数是很像的。

好了,我们已经定义了⼀个函数模板,那么怎么去⽣成函数代码?事实上我们不需要做额外的事情,如果我们使⽤了max函数,编译器就会⾃动帮我们⽣成对应类型的代码。

函数模板的使⽤⽅式很简单,只需要在模板的名字后⾯写⼀对尖括号,尖括号内写上实参列表就可以使⽤了。

double d = max<double>(1.2, 2.4);
编译器看到这⼀⾏,就会⾃动帮我们⽣成double版本的max函数,⽣成出来的函数等价于把函数模板中的所有T都替换成double。

在这⾥max<double>可以看做是double版本的max函数的函数名,我们甚⾄还可以⽤&max<double>来获取这个函数的地址。

我们来看⼀个更复杂的例⼦
template<typename T, int i>
T create()
{
T value();
return value + i;
}
int main()
{
float f1 = create<float, 1>(); // f1 == 1.0
float f2 = create<float, 2>(); // f2 == 2.0
}
这个例⼦⾥⾯我们定义了⼀个create函数模板,根据模板创建并使⽤了两个函数create<float, 1>和create<float, 2>。

要注意的是,这两个函数是不同的函数,有不同的函数体,和不同的函数地址。

他们两个分别等价于
float create() // create<float, 1>
{
float value();
return value + 1;
}
float create() // create<float, 2>
{
float value();
return value + 2;
}
我们总结⼀下函数模板的语法,模板定义由template关键字开始,后⾯跟着⼀对尖括号,尖括号⾥⾯是模板形参列表,也就是模板的参数。

模板形参列表的写法和函数形参列表的写法是很相似的。

都是“类型参数名, 类型参数名, ...”这种形式。

上⾯的例⼦中,模板形参列表就
是“typename T, int i”。

我们注意到,模板形参列表需要为每个形参指定⼀个类型,这个是因为形参不⼀定是C++类型,还可以是具体的值,例如数字,指针等等。

如果形参是⼀个类型,则需要使⽤typename关键字来表⽰形参的类型,如果形参是⼀个值,则需要写上这个值的类型。

在使⽤模板的时候,要在模板的名字后⾯加⼀对尖括号,尖括号⾥⾯是模板实参列表,在上⾯的例⼦中,实参列表就是“float, 1”和“float, 2”。

与函数调⽤类似,使⽤模板的时候编译器会检查实参列表的类型与形参列表的类型是否匹配,不匹配的话会报错。

使⽤函数模板的优点
我们可以从上⾯的例⼦中看出,⽤函数模板更⽅便简洁,不需要重复写类似的重载函数。

除此外,因为函数代码是在使⽤的时候⽣成出来的,所以如果我们没有使⽤这个函数,编译器就不会⽣成这个代码,这样我们可以减⼩程序的⼤⼩。

例如,我们使⽤了max<double>,但是没有使⽤max<int>,那么程序中只有max<double>函数,不会有max<int>函数。

相关文档
最新文档