活着就意味必须要做点什么,请好好努力。
------《地下》
模版是泛型编程的基础, 模版分为 函数模版 和 类模版
template <class(或typename) 形参名1, class 形参名2, class 形参名n>
返回类型 函数名(参数列表)
{...}
模板形参的定义既可以使用class,也可以使用typename,含义是相同的.
//一个简单的函数模板,比较 left 和 right, 与类型无关
template<typename T>
bool IsEqual (const T& left , const T& right )
{
return left == right;
}
void test1 ()
{
string s1 ("s1"), s2("s2" );
IsEqual (s1, s2);
IsEqual (1,1);
}
模板参数匹配及显示实例化
template <typename T>
bool IsEqual (const T& left , const T& right )
{
return left == right;
}
void test1 ()
{
cout<<IsEqual (1,1)<<endl;
//cout<
cout<<IsEqual<int>(1,1.2)<< endl; // 显示实例化
cout<<IsEqual<double>(1,1.2)<< endl; // 显示实例化
}
重载函数模板
bool IsEqual (const int& left , const int& right)
{
return left == right;
}
template <typename T>
bool IsEqual (const T& left , const T& right )
{
return left == right;
}
template <typename T1, typename T2>
bool IsEqual (const T1& left , const T2& right)
{
return left == right;
}
void test1 ()
{
cout<<IsEqual(1,1)<<endl;
cout<<IsEqual<int>(1,1)<< endl;
cout<<IsEqual(1,1.2)<<endl;
}
函数会 优先调用 最适合自己的函数
函数模板重载四大规则
<>
的语法限定编译器只通过模板匹配template <class 形参名1, class 形参名2, ...class 形参名n>
class 类名
{ ... }
模板类实例
//动态顺序表
template<typename T>
class SeqList
{
public :
SeqList();
~ SeqList();
private :
int _size ;
int _capacity ;
T* _data ;
};
template <typename T>
SeqList <T>:: SeqList()
: _size(0)
, _capacity(10)
, _data(new T[ _capacity])
{}
template <typename T>
SeqList <T>::~ SeqList()
{
delete [] _data ;
}
void test1 ()
{
SeqList<int> sl1;
SeqList<double> sl2;
}
模板类的实例化
类模板是用来生成类的蓝图的。
与函数模板的不同之处是:编译器不能为类模板推断模板参数类型。
为了使用类模板,我们必须在模板名后的尖括号中提供额外信息——用来代替模板参数的模板实参列表。
##非类型模板参数&模板的模板参数
####模板参数–实现容器适配器
template
class SeqList
{
private :
int _size ;
int _capacity ;
T* _data ;
};
// template
template > // 缺省参数
class Stack
{
public :
void Push (const T& x );
void Pop ();
const T & Top();
bool Empty ();
private :
Container _con ;
};
void Test ()
{
Stack s1;
Stack> s2 ;
// 思考下面这种使用场景会怎样?
Stack> s3 ;
}
####模板的模板参数–容器适配器
template <typename T>
class SeqList
{
private :
int _size ;
int _capacity ;
T* _data ;
};
// template class Container>
template <class T, template <class> class Container = SeqList > // 缺省参数
class Stack
{
public :
void Push (const T& x );
void Pop ();
const T & Top();
bool Empty ();
private :
Container<T > _con;
};
void Test ()
{
Stack<int > s1;
Stack<int , SeqList> s2;
}
####非类型的类模板参数
// 静态顺序表
//template
template <typename T, size_t MAX_SIZE = 10> //带缺省模板参数
class SeqList
{
public :
SeqList();
private :
T _array [MAX_SIZE];
int _size ;
};
template <typename T, size_t MAX_SIZE>
SeqList <T, MAX_SIZE>::SeqList ()
: _size(0)
{}
void Test ()
{
SeqList<int > s1;
SeqList<int , 20> s2;
}
####非类型的模板函数参数
template
T Add (const T& x )
{
return x + value;
}
浮点数和类对象是不允许作为非类型模板参数的
//template //error
template //error
class Test
{
private :
double _value ;
};
补充:
C++ 中 typename 和 class 的区别
在 C++ Template 中很多地方都用到了 typename 与 class 这两个关键字,而且好像可以替换,是不是这两个关键字完全一样呢?
相信学习 C++ 的人对 class 这个关键字都非常明白,class 用于定义类,在模板引入 c++ 后,最初定义模板的方法为:
template<class T>......
这里 class 关键字表明T是一个类型,后来为了避免 class 在这两个地方的使用可能给人带来混淆,所以引入了 typename 这个关键字,它的作用同 class 一样表明后面的符号为一个类型,这样在定义模板的时候就可以使用下面的方式了:
template<typenameT>......
在模板定义语法中关键字 class 与 typename 的作用完全一样。
typename 难道仅仅在模板定义中起作用吗?其实不是这样,typename 另外一个作用为:使用嵌套依赖类型(nested depended name),如下所示:
class MyArray
{
public:
typedef int LengthType;
.....
}
template<class T>
void MyMethod( T myarr )
{
typedef typename T::LengthType LengthType;
LengthType length = myarr.GetLength;
}
这个时候 typename 的作用就是告诉 c++ 编译器,typename 后面的字符串为一个类型名称,而不是成员函数或者成员变量,这个时候如果前面没有 typename,编译器没有任何办法知道 T::LengthType 是一个类型还是一个成员名称(静态数据成员或者静态函数),所以编译不能够通过。
模板(二):模板的特化与模板的分离编译
模板(三):模板之类型萃取(TypeTraits)