一、什么是模板
模板是一种编程工具。它可以让代码具有通用性(让多个不同的类型使用同一个模板)。
模板的声明:
template<class T>
或
template<typename T>
二、模板
2.1函数模板
将函数的参数用模板表示。
template<class T>
void Swap(T& a, T& b)//T为模板类型(可以是任何类型)
{
T c = a;
a = b;
b = c;
}
int main() {
int a = 0;
int b = 1;
char c = 0;
swap(a, c);//T无法代表两种不同的类型,这么写会报错
Swap(a, b);//编译器会自动推导出参数的类型
cout << "a:" << a << endl;
cout << "b:" << b << endl;
}
当然,函数模板也能作为返回类型。
template<class T>
//T也可以作为返回类型
T Add(T& a, T& b)
{
return a + b;
}
int main() {
int a = 0;
int b = 1;
//不想用自动类型推导,可以用<>来指定类型传参
cout << Add<int>(a, b) << endl;
}
模板类型也可以定义多个,每个模板类型互不相通,但也可以转为同一个类型。
template<class T,class Y>
T Add(T& a, Y& b)
{
cout << "函数模板调用";
return a+b;
}
int main() {
int a = 0;
char b = 1;
cout << Add(a, b) << endl;//此时的T是int Y是char
cout << Add(a, c) << endl;//此时的T是int Y也是int
}
注:*模板作为返回类型时,该参数中至少有一个参数的类型也是同名模板,否则编译器无法得知你要返回什么。
template<class T>
//参数中没有T类型,编译器无法得知你想返回什么
T Add(int& a, int& b)
{
return a + b;//万一你想返回char呢?
}
int main() {
int a = 0;
int b = 1;
cout << Add(a, b) << endl;
}
*模板调用的优先级:能调用普通函数时,不会调用模板函数。
使用 “ <> ” 可以指定编译器调用模板。
2.2模板特化
模板不是万能的,模板也解决不了某些情况。如:
class Date
{
public:
Date(int day)
{
_day = day;
}
public:
int _day = 0;
};
template<class T>
int Add(T& a, T& b)
{
cout << "函数模板调用";
return a+b;
}
int main() {
Date d1=1;
Date d2=2;
cout << Add(d1, d2) << endl;//自定义类型无法比较,运行会报错
}
此时使用模板特化,让模板函数遇到这种情况时特殊处理。
class Date
{
public:
Date(int day)
{
_day = day;
}
public:
int _day = 0;
};
template<class T,class Y>
int Add(T& a, Y& b)
{
cout << "函数模板调用";
return a+b;
}
template<>
int Add<Date,Date>(Date& d1,Date& d2)//使用该句式特化模板
{
cout << "模板特化";
return d1._day + d2._day;
}
int main() {
Date d1=1;
Date d2=2;
cout << Add(d1, d2) << endl;//传入模板特化指定的类型后,就会调用特化模板
}
2.3类模板
2.3.1类模板的创建
模板也适用于类。
模板类中的成员函数在调用时才会被创建。普通成员函数在一开始就会创建。
template<class T = int>//类模板的模板参数可以有默认值
class Date
{
public:
Date(T day):_day(day)
{
_day = day;
}
T showday()
{
cout << _day << endl;
}
public:
T _day = 0;
};
int main() {
Date<int> d1=1;//类模板没有自动类型推导
Date<char> d2=2;//需要手动添加类型
Date<>d3 = 3;//使用默认值
}
2.3.2模板类对象做函数参数
template<class T = int>
class Date
{
public:
Date(T day):_day(day)
{
_day = day;
}
void showday()
{
cout << _day << endl;
}
public:
T _day = 0;
};
//三种传参方式
void show(Date<char>& d)//指定类型传参
{
d.showday();
}
template<class T>
void show(Date<T>& d)//参数模板化传参
{
d.showday();
}
template<class T,class Y>
int Add(T& a, Y& b)//对象模板化传参
{
cout << "函数模板调用";
return a+b;
}
template<>
int Add<Date<int>, Date<int>>(Date<>& d1, Date<int>& d2)
{
cout << "模板特化";
return d1._day + d2._day;
}
2.3.3模板类成员类外实现
类外实现的模板类成员需要重新写一遍template
template<class T = int>
class Date
{
public:
Date(T day);
void showday();
public:
T _day = 0;
};
//成员函数类外实现
template<class T>
Date<T>::Date(T day)
{
_day = day;
}
template<class T>
void Date<T>::showday()
{
cout << _day;
}
注:模板类不能分文件编写。