1.为什么要使用模板?
对于特点相似的类,比如有相同的方法相似的成员,使用模板可以使得这些类得到进一步的抽象。也就是写一个超级形态的类。这样至少有一个浅显的好处,只用写一次。但实际上,可能更方便维护,也具有更一直的特性。对于函数,作用也类似,也就是形成一个函数簇,这个函数簇的所做的动作是高度相似的。使用模板函数的益处也相似。
2.模板类怎么写?
模板类的申明如下
template <class T>
class MyClass1 {
// C++98就开始支持
}
template <typename T, typename U=int, U v=0>
class MyClass2 {
// C++98就开始支持
}
实际使用模板类时,需要先指定T的实际类型
MyClass1<int> myClass;
//c++1.0中,连续两个>>会被认为是右移
//c++2.0中,连续>>编译器会判断是右移还是两个模板符合
3 模板函数怎么写?
template <typename T, typename U> int foo(T v)
{
// 函数的主体
}
template <typename T, typename U=int>
{
// C++2.0支持,C++2011及其之后的版本
}
模板函数的调用不用指定T的实际类型,编译器会在调用时自动推导
4 模板参数中typename和class有什么区别?
typename 说明T是一种类型,这种类型可以是基本类型也可以是类。
class 说明T只能是类。
5 可变参数模板是什么?
C++98/03的版本中,模板中的模板参数(也就是上面的T、U之流)是固定的,也就是1个2个还是3个,反正写的时候就必须写死。但是C++2.0(也就是C++2011/14/17/20)允许不写死,也就是你在声明的时候自己也不知道要写几个而是直接声明一个参数包。
6 采用递归方式的可变参数模板函数怎么写?
可变参数模板函数有两种实现方式,一种是采用递归方式,一种是采用初始化列表方式
//2. 定义边界处理函数,即递归调用结束时如何处理
void print()
{
//如果没有定义第8行的函数,则会执行此函数作为结束递归的边界
cout<<"no element:end\n";
}
template <typename HEAD> //注意模板参数必须在紧邻函数前进行申明
void print(HEAD arg0)
{
//这个函数设计用来说明可以指定递归到最后一参数时作为结束递归的边界
cout<<arg0<<"\n";
cout<<"last element:end\n";
}
//1. 定义初始参数类型和包类型,注意至少要定义一个确定的类型,这里是HEAD ...就被称为包
template <typename HEAD, typename... T> //...紧跟typename或者class
void print(HEAD arg0,T... args)//...紧跟T
{
cout<<arg0<<"\n";
print(args...);//递归调用, ...紧跟args表明自己后面是个包
}
int main(){
print(1,2,"test");
/* 执行结果如下
1
2
test
last element:end
*/
}
7 可变参数模板类怎么写?
可变参数模板的实现方式有好几种,递归,继承,使用结合萃取机,只理解了最简单的递归,但这种方法能够实现的东西很受限。
template<typename... args> class MyTuple; // 1.前向声明 ,说明MyTuple是一个可变参数模板类
template<typename HEAD,typename... OTHER>// 2.声明递归类型,用来参数解包
class MyTuple<HEAD,OTHER>
{
}
template<typename LAST>// 3.声明边界类型,特化来终止递归解包
class MyTuple<LAST>
{
}