什么是模板?
有的时候需要使用功能相似的函数或者类,它们的区别仅仅只是数据类型的不同。这时候做重复的工作,敲相同的代码显得很没有必要。为了避免重复的工作c++引入了模板的概念,用相同的一套代码,让编译器自己在编译的时候根据给到的类型,生成相应的版本。
c++中模板应用非常广泛,各种的STL以及一些标准库的类型都用到了模板。
例子
//vector容器
vector<int> MyVector;
//数对类型
pair<int,string> tData = {2,"pair"};
pair<int,string> tData = make_pair<int,string>(2,"pair");
类模板严格意义上不是真正的类,不能分开文件写定义和实现,应该写在同一个文件里
一、函数模板
template<typename T>
T Max(T a, T b)
{
return a > b ? a : b;
}
隐式调用:根据数据推断类型(要能够推断,有推断依据)
Max(1,2); //int
Max(1.1,2.2); //double
显示调用
Max<int>(1,2);
允许使用多个未知类型
template<typename T1, typename T2> //以“,”隔开
二、模板类
- 在用到类名的地方都需要:类名<数据类型>的方式使用
- 模板类必须显示调用,不能隐式调用
template<class T>
class MyClass
{
public:
MyClass(T data):m_data(data){}
T m_data;
void print(T pdata);
};
template<class T>
void MyClass<T>::print(T pdata)
{
}
//使用
MyClass<int> class(1);
MyClass<int>* pC = new MyClass<int>(1);
类中的成员函数仍然可以隐式调用,不过得是带参数的(会自动推断)。
三、以结构体为类型(以类为类型)
struct Info
{
int m_id;
string m_name;
Info(int id, string name) :m_id(id), m_name(name) {}
};
template<class T>
class MyClass
{
public:
MyClass(T data):m_data(data){}
T m_data;
};
//使用
Info i(1,"XiaoMing");
MyClass<Info> class1(i);
如果需要对结构体进行赋值,计算等操作,可以使用重载
四、模板中可以带有变量
template<class T, int size>
class MyClass
{
public:
void print(T data);
};
template<class T, int size>
void MyClass<T, size>::print(T data)
{
cout<<data<<endl;
cout<<size<<endl; //可以使用size变量
}
MyClass<int,3> class1; //创建对象
“3”的位置不允许传递变量。
五、模板的嵌套
template<class T>
struct Info
{
int m_id;
string m_name;
T m_data;
Info(int id, string name, T data) :m_id(id), m_name(name), m_data(data) {}
};
template<class T>
class MyClass
{
public:
T m_data;
MyClass(T data) :m_data(data) {}
};
//使用
Info<int> i(1,"xiao",10);
MyClass<Info<int>> class1(i);
这种用法和上面的结构体作为类型有点相似,唯一不同点是这里结构体也是模板,也需要类型输入,所以想当于嵌套了模板。
当嵌套的模板过多时,可以使用起别名的方法避免造成混乱。
using InfoType = Info<int>;
MyClass<InfoType> class1(i);