概述
用类模板实例化一个特定的类。
编译器不能为类模板推断模板参数类型,所以为了使用类模板,我么必须在模板后边用<>来提供额外的信息,这些信息其实就是对应着模板参数列表中的参数。例如:vector<int>
目的:同一套代码可以应付不同的 数据类型,这样就精简多了。
类模板定义
template<typename 形参名1, typename 形参名2, .....typename 形参名n>
class 类名
{
};
我们实例化类模板时,必须要又类的全部信息,包括类模板中成员函数函数体。
//myvector.h
#ifndef __MYVECTOR__
#define __MYVECTOR__
template<typename T>
class myvector{
public:
typedef T* myiterator;
public:
myvector(); //构造函数
myvector& operator=(const myvector &); //赋值运算符重载。在模板内部不需要提供
//模板参数
public:
myiterator mybegin(); //
myiterator myend(); //
public:
void myfunc();
};
template <typename T> //类模板函数外部实现
void myvector<T>::myfunc()
{
return;
}
template <typename T>
myvector<T>& myvector<T>::operator=(const myvector &) //第一个<T>表示返回的是一
//个实例化了的myvector
{
return *this;
}
#endif
//------------------------------------------------------------
//file.cpp
int main(){
myvector<int> typvec;
typvec::myiterator iter; //声明迭代器
}
myvector 是一个类模板名,不是一个他不是一个类名,类模板是用来实例化类(类型)用的。
myvector<int>才是类型名。
所以,一个实例化的类型总会用尖括号<>包含着模板参数。
一个类模板虽然可能有很多成员函数,但是当你实例化模板之后,如果你后续没有使用到某个成员函数,则这个成员函数不会被实例化,说白了,就是一个实例化的模板,它的成员函数只有在使用的时候才被实例化。
模板类名字的使用
类模板的成员函数
类模板成员函数,可以写在类模板定义中{};那么这种写在类模板定义中的成员函数会被隐式声明为 inline 函数。
类模板一旦被实例化之后,那么这个模板的每个实例都会有自己的成员函数。所以,类模板的成员函数具有和这个类模板相同的模板参数(这句话的核心意思是:类模板的成员函数是有模板参数的)
如果把类模板成员函数的的定义卸载(函数体)外边,那么这个成员函数的模板参数就体现出来了。
定义在类模板之外的成员函数必须以关键字template开始,后边接类模板参数列表,同时在在类名后边要用<>把模板参数列表的所有模板参数名列出来,如果是多个模板参数,用“,”分割。
非类型模板参数
//myarray.h
#ifndef __MYARRARY__
#define __MYARRARY__
template<typename T, int size = 10>
class myarray{
private:
T arr[size];
public:
void myfunc();
}
template<typename T, int size>
void myarrary<T,size>::myfunc()
{
return;
}
#endif
//file.cpp
#include "myarrary.h"
int main(){
}
限制
1、浮点型数据不能做非类型模板参数。比如:double,float
2、类类型也不允许做非类型模板参数
class A {};
template<typename T, A a> //不可以,报错
class myclass
{
};