模板是c++的一种特性,允许函数或者类(对象)通过泛型(generic types)的形式表现或者运行
模板可以使得函数或类在对应不同的类型(types)的时候正常工作,而无需为每一种类型分别写一份代码。
1:函数模板(function tempalte):使用泛型参数的函数(function with generic parameters)
2:类模板(class template):使用泛型参数的类(class with generic parameters)
模板的声明(declaration)其实并未给出一个函数或者类的完全定义(definition),只是提供了一个函数或者类的语法框架(syntactical skeleton)
实例化是指从模板构建出一个真正的函数或者类的过程。用具体类型代替模板参数的过程叫做实例化;从而产生一个模板实例。
如果实例化一种类型,而该类型并不支持函数所使用的操作,那么就会导致一个编译错误。
1:显示实例化-在代码中明确指定要针对哪种类型进行实例化
2:隐式实例化-在首次使用时根据具体情况使用一种合适的类型进行实例化
函数模板编译(两次):
1:没有实例化之前,检查代码本身是否有语法错误。
2: 实例化期间,检查对模板代码的调用是否合法。
函数模板是参数化的一族函数(a famliy of functions)
通过函数模板,可以实例化一系类函数,这些函数都给予同一套模板框架,但是作用在不通类型的参数上
示例 :(针对不同的数据类型 比较两个数据的大小)
#include
template //模板参数由关键字typename(也可以使用class) 定义 定义一个函数模板 返回两个数中数值大的那一个
inline T max(const T &a,const T &b)//函数有两个参数 ,类型为定义
{
return a>b?a:b;
}
int main()
{
int a =1;
int b =2;
auto ret = max(a,b);
std::cout<<"int ret = "<#include
template //模板参数由关键字typename(也可以使用class) 定义 定义一个函数模板 返回两个数中数值大的那一个
inline T max(const T &a,const T &b)//函数有两个参数 ,类型为定义
{
return a>b?a:b;
}
int main()
{
int a =1;
double b =2.0;
//auto ret = max(a,b); //error 模板只有一种参数 但是这里传入了两种类型的参数
//解决办法
//用static_cast 强制转换参数类型使得 参数匹配
auto ret1 = max(static_cast(a),b);
//显示指定T的类型
auto ret2 = max(a,b);
return 0;
}
参数不匹配报错
函数模板重载
#include
template //模板参数由关键字typename(也可以使用class) 定义 定义一个函数模板 返回两个数中数值大的那一个
inline T max(const T &a,const T &b)//函数有两个参数 ,类型为定义
{
return a>b?a:b;
}
#include
template
inline T max(const T &a,const T &b,const T &c)
{
T temp;
if(ac?temp :c;
}
inline int max(const int &a,const int &b)
{
return a>b?a:b;
}
template
inline T max(const T &a,const T1 &b)
{
std::cout<<"template "<b?a:b;
}
int main()
{
max(1,2,3); // max(const T &a,const T &b,const T &c) max
max(1.0,2.3); //max(const T &a,const T &b) max
max('a','b'); //max(const T &a,const T &b) max
max(1,2); //inline int max(const int &a,const int &b)
max<>(1,2); //max(const T &a,const T &b) max
max(1,2); //max(const T &a,const T &b) max
max('a',2); //inline int max(const int &a,const int &b)
return 0;
}
与函数模板类似,类也可以通过参数泛化,从而可以构建出一族不同的类实例(对象)
类模板实参可以是某一类型或常量(仅限int或enum)
示例
#include
#include
/*********************************************************
*T可以是任意类型
*模板实参也可以是一个int或enum类型的常量 size_t实际是int类型
*n是编译时定义的常量
*n可以有默认值
*size_t类型的成员变量可以用n初始化
***********************************************************/
const std::size_t DefaultStackSize = 1024;
template
class Stack
{
public:
void Push(const T &element);
int Pop(T &element);
//int Top(T &element) const;
private:
std::vector m_Members;
std::size_t m_mMaxSize = n;
};
template
void Stack::Push(const T &element)
{
if(m_mMaxSize <= m_Members.size())
{
return;
}
m_Members.push_back(element);
}
template
int Stack::Pop(T& element)
{
if(m_Members.empty())
{
return -1;
}
element = m_Members.back();
m_Members.pop_back();
return 0;
}
int main()
{
Stack stack;
Stack stack1;
for(int i =0;i<100;i++)
{
stack.Push(i);
}
int i;
stack.Pop(i);
std::cout<
允许对一个类模板的某些模板参数类型做特化
对于某种特殊的类型,可能可以做些特别的优化或提供不同的实现
避免在实例化的时候引起一些可能不好的行为
特化一个类模板的时候也意味着需要特化其所有参数化的成员函数
示例:
#include
#include
/*********************************************************
*T可以是任意类型
*模板实参也可以是一个int或enum类型的常量 size_t实际是int类型
*n是编译时定义的常量
*n可以有默认值
*size_t类型的成员变量可以用n初始化
***********************************************************/
const std::size_t DefaultStackSize = 1024;
template
class Stack
{
public:
void Push(const T &element);
int Pop(T &element);
//int Top(T &element) const;
private:
std::vector m_Members;
std::size_t m_mMaxSize = n;
};
template
void Stack::Push(const T &element)
{
if(m_mMaxSize <= m_Members.size())
{
return;
}
m_Members.push_back(element);
}
template
int Stack::Pop(T& element)
{
if(m_Members.empty())
{
return -1;
}
element = m_Members.back();
m_Members.pop_back();
return 0;
}
template <>
class Stack
{
public:
void Push(const T &element);
int Pop(T &element);
//int Top(T &element) const;
private:
std::list m_Members;
std::size_t m_mMaxSize;
};
int main()
{
Stack stack;
Stack stack1;
for(int i =0;i<100;i++)
{
stack.Push(i);
}
int i;
stack.Pop(i);
std::cout<
类模板也可以偏特化
template
class MyClass
{
};
//偏特化
template
class MyClass
{};
template
class MyClass
{};
template
class MyClass
{};