模板参数分为 类型模板参数(C++模板的零基础讲解)和非类型模板参数。
看下面的代码
#define N 10
//T就是类型模板参数
template<class T>
class Array
{
private:
T a[N];
};
int main()
{
Array<int> a1;
Array<double> a2;
return 0;
}
上面这个就是类型模板参数,能够创建不同类型的数组。
但是现在有一个要求将a1
数组的大小设置为10,a2
的大小设置为100.
上面这个操作并不可以完成。
类型模板参数定义的是类型,而非类型模板参数定义的就是整型常量。
注意只能是整型,可以这样认为祖师爷就是为了设置数组的大小所以设置非类型模板参数。
并且不能修改,这个也很容易理解不能改变数组的大小。
//T就是类型模板参数
template<class T,size_t N = 20>
class Array
{
private:
T a[N];
};
int main()
{
Array<int,10> a1;
Array<double,100> a2;
return 0;
}
这样我们就可以定义不同大小的数组。
我先给你们看一个日期类,然后在进行我们下面的操作
class Date
{
public:
Date(int year = 1900, int month = 1, int day = 1)
: _year(year)
, _month(month)
, _day(day)
{}
bool operator<(const Date& d)const
{
return (_year < d._year) ||
(_year == d._year && _month < d._month) ||
(_year == d._year && _month == d._month && _day < d._day);
}
bool operator>(const Date& d)const
{
return (_year > d._year) ||
(_year == d._year && _month > d._month) ||
(_year == d._year && _month == d._month && _day > d._day);
}
friend ostream& operator<<(ostream& _cout, const Date& d)
{
_cout << d._year << "-" << d._month << "-" << d._day;
return _cout;
}
private:
int _year;
int _month;
int _day;
};
现在的要求是,利用我们的比较类,比较日期的大小。
// 函数模板 -- 参数匹配
template<class T>
bool Less(T left, T right)
{
return left < right;
}
int main()
{
//比较int类型的数字
cout << Less(1, 2) << endl; // 可以比较,结果正确
//比较两个日期类
Date d1(2022, 7, 7);
Date d2(2022, 7, 8);
cout << Less(d1, d2) << endl; // 可以比较,结果正确
比较两个日期类的指针
Date* p1 = &d1;
Date* p2 = &d2;
cout << Less(p1, p2) << endl; // 可以比较,结果错误
return 0;
}
对于比较两个int类型我就不用过多说明。
比较两个日期类,我们在日期类中重载了<
,所以可以按照我们想要的要求去比较。
但是对于第三个,我们想要比较指针指向的内容,但是我们比较的时候确实比较的指针,这是不符合我们的要求的。
这时就需要用到模板特化
模板特化就是对某些类型进行特殊化处理
// 函数模板 -- 参数匹配
template<class T>
bool Less(T left, T right)
{
return left < right;
}
//模板特化
template<>
bool Less<Date*>(Date* left, Date* right)
{
return *left < *right;
}
但是都是建立再原模版之上的。
必须有原模板,才能有特化。
这是针对某个具体的类型进行特化。
template<class T>
struct Less
{
bool operator()(const T& left, const T& right)
{
return left < right;
}
};
//类模板的特化
template<>
struct Less<Date*>
{
bool operator()(const Date* left, const Date* right)
{
return *left < *right;
}
};
测试全特化
int main()
{
Date d1(2022, 7, 7);
Date d2(2022, 7, 8);
cout << Less<Date>()(d1, d2) << endl;
Date* p1 = &d1;
Date* p2 = &d2;
cout << Less<Date*>()(p1, p2) << endl;
return 0;
}
下面这个叫做偏特化,就是一种范类进行限制(比如下面的指针)
当这个类有多个模板参数,也可以对部分参数进行偏特化。
可以对任意类型特化,甚至是引用。
template<class T>
struct Less
{
bool operator()(const T& left, const T& right)
{
return left < right;
}
};
//偏特化
template<class T>
struct Less<T*>
{
bool operator()(const T* left, const T* right)
{
return *left < *right;
}
};
int main()
{
Date d1(2022, 7, 7);
Date d2(2022, 7, 8);
cout << Less<Date>()(d1, d2) << endl;
Date* p1 = &d1;
Date* p2 = &d2;
cout << Less<Date*>()(p1, p2) << endl;
int* a = new int(1);
int* b = new int(2);
cout << Less<int*>()(a, b) << endl;
return 0;
}
测试偏特化
int main()
{
Date d1(2022, 7, 7);
Date d2(2022, 7, 8);
cout << Less<Date>()(d1, d2) << endl;
Date* p1 = &d1;
Date* p2 = &d2;
cout << Less<Date*>()(p1, p2) << endl;
return 0;
}
首先,先记住一点也是最重要的一点,
模板不支持在两个文件的分离编译。