一、模板
1、目的
编写与类型无关的代码。
2、概念
模板是一种对类型进行参数化的工具,通常有两种形式:
1)函数模板
函数模板针对仅参数类型不同的函数
参数类型不一样的但是功能及函数名一致的函数
template <class形参名,class形参名,......>返回类型函数名(参数列表)
{
函数体
};
2)类模板
类模板针对仅数据成员和成员函数类型不同的类
成员属性的类型和成员函数的类不一样但是成员属性及函数一样的类
template<class形参名,class形参名,…>class类名
{
函数体
};
注意:
模板的声明或定义只能在全局,命名空间或类范围内进行。即不能在局部范围,函数内进行,比如不能在main函数中声明或定义一个模板。声明数据类型参数标识符的关键字既可以用class也可以用typename
二、函数模板
1、目的
编写与类型无关的代码
2、函数模板
当函数功能和函数名一致但参数类型不同时,需要定义函数模板
3、语言形式
template <class 形参名1, typename 形参名2, ......>
返回值 函数名(参数列表)
{
函数体
}
eg:函数模板
#include <iostream>
using namespace std;
template <class T>
T add(T &a, T &b)
{
T c = a+b;
return c;
}
int main()
{
int m = 52;
int n = 1314;
int c = add<int>(m, n);
cout << "c = " << c << endl;
return 0;
}
结果:
三、类模板
1、类模板
当类名和成员变量及成员函数的名字一致,但成员变量和函数的类型不同的时候就需要定义成类模板;
2、语法形式
template <class 形参名1,typename 形参名2, .......>
class 类名{
成员变量和成员函数;
};
eg:类模板
#include <iostream>
using namespace std;
template <class T>
class Demo
{
public:
Demo(T val):val(val)
{
cout << __func__<<": "<<__LINE__<<endl;
}
~Demo()
{
cout << __func__<<": "<<__LINE__<<endl;
}
void setval(T val)
{
this->val = val;
}
T getval()const;
private:
T val;
};
template <class T>
T Demo<T>::getval()const
{
return this->val;
}
int main()
{
Demo<int> obj(52);
cout<<obj.getval()<<endl;
obj.setval(1314);
cout<<obj.getval()<<endl;
return 0;
}
结果:
四、非类型模板参数
1、理解
参数列表中定义的确定类型的变量
2、示例
template <class T, int var> //T:类型形参名 var:非类型模板参数
class 类名
{
成员变量和成员方法
};
eg:
#include <cassert>
#include <iostream>
using namespace std;
template <class T, int len> // len:数组长度
class Array
{
public:
Array()
{
ptr = new T[len];
assert(NULL!=ptr);
cout << __func__<<": "<<__LINE__<<endl;
}
~Array()
{
delete [] ptr;
cout << __func__<<": "<<__LINE__<<endl;
}
void setval(int index, T val)
{
ptr[index] = val;
}
T getval(int index)const;
private:
T *ptr;
};
template <class T, int len>
T Array <T, len>::getval(int index)const
{
return ptr[index];
}
int main()
{
Array <int, 10> a;
int i = 0;
for(i = 0; i < 10; i++)
a.setval(i,i+1);
for(i = 0; i < 10; i++)
cout<<"get: "<<a.getval(i)<<" ";
return 0;
}
注意:
非类型形参在模板定义的内部是常量值
非类型模板的形参只能是整型、指针和引用,像double,string,string **这样
的类型是不允许的。但是double &, double *,对象的引用或指针是正确的。非类型模板形参的实参如果是表达式,则必须是一个常量表达式,在编译时计算出结果。
非类型模板形参和实参间允许类型转换
五、默认类型模板参数
1、理解
可以给类模板的模板形参指定默认类型
2、示例
template<class T>
class Demo
{
public:
Demo(T val) : val(val)
{
cout << __func__ << ":" << __LINE__ << endl;
}
~Demo()
{
cout << __func__ << ":" << __LINE__ << endl;
}
void setval(T val)
{
this->val = val;
}
T getval() const;
friend template<class M>
ostream &operator <<(ostream &,const Demo<M> &);
private:
T val;
};
//类外部成员定义成员方法
template<class T>
T Demo<T>::getval() const
{
return this->val;
}
template<class >
ostream &operator <<(ostream &os,const Demo<T> & obj)
{
os << obj.val;
return os;
}
int main()
{
Demo<int> obj(666);
cout << obj << endl;
return 0;
}