模板
非类型模板参数
#define N 10
template<class T>
//静态的数组
class Array
{
private:
T _a[N];
};
int main()
{
Array<int> a1; //这样子数组已经写死了!
Array<double> a2; //如果我们不想要10想要其他的大小那么我们就必须修改宏!这样子其实是不方便的!
return 0;
}
==如果我们想要一个能够灵活定义的固定数组
==这时候宏就不够方便灵活了!为了能够适应这种状况!于是就有了非类型模板参数!==
template<class T,size_t N = 10>//模板可以有缺省值
class Array
{
private:
T _a[N];
};
int main()
{
Array<int,10> a1;
Array<double,10000> a2;
//这样就可以规定我们想要的固定的数组大小了!
return 0;
}
==非类型模板参数是一个整形常量!==
实际中C++的STL库的array里面也是使用非类型模板参数来实现了的!
==函数模板也是可以使用这个非类型模板参数==
template<class T,size_t N>
void Func(const T& x)
{
cout << N << endl;
}
template<class T,double N>
void Func2(const T& x)
{
cout << N << endl;
}
int main()
{
Func<int, 100>(1);
FUnc2<int,1.00>(1);
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 x, T y)
{
return x < y;
}
int main()
{
cout << Less(1, 2) << endl; //结果正确
Date d1(2019, 1, 1);
Date d2(2019, 1, 2);
cout << Less(d1, d2) << endl; //结果正确
Date* p1 = &d1;
Date* p2 = &d2;
cout << Less(p1, p2) << endl; //可以比较但是结果错误
return 0;
}
==为什么会发生这种情况呢?因为我们希望的比较的不是日期类的指针的地址的大小!而是希望比较日期类的内容!==
==所以如果能够对针对某些类型进行特殊处理那就是最好的!==
这种特殊处理我们就叫做特化!
template<class T>
bool Less(T x, T y)
{
return x < y;
}
//对于Date*类型进行偏特化!
template<>
bool Less<Date*>(Date* x, Date* y)
{
return *x < *y;
}
==这样子就可以符合我们想要的行为了!==
==下面的会去调用特化的哪一个!==
类模板的特化
全特化
template<class T1, class T2>
class Base
{
public:
Base()
{
cout << "Base<T1,T2>" << endl;
}
public:
T1 _d1;
T2 _d2;
};
//假设如果我们想要对某种特定类进行特殊处理的话我们应该办?
//函数模板可以写一个普通的函数出来!但是类就不可以了!
//这就是对上面类的特化
template<>
class Base<double, double>
{
public:
Base()
{
cout << "Base<double,double>" << endl;
}
private:
};
//里面的内容可以自由定义,只是说如果是double的参数,那么就是用这个特化的模板类!不一样是要一样的!
int main()
{
Base<int, int> b1;
Base<double, double> d1;
return 0;
}
半特化/偏特化
全特化的意思就是对全部的模板参数进行特化!
半特化就是只对部分的参数进行特化!
template<class T1, class T2>
class Base
{
public:
Base()
{
cout << "Base<T1,T2>" << endl;
}
public:
T1 _d1;
T2 _d2;
};
template<>//全特化
class Base<double, char>
{
public:
Base()
{
cout << "Base<double,char>" << endl;
}
private:
};
template<class T>//偏特化
class Base<T, char>
{
public:
Base()
{
cout << "Base<T,char>" << endl;
}
private:
};
int main()
{
Base<int, int> b1;
Base<int ,char> b2;//优先匹配偏特化
Base<long long ,char> b3;//优先匹配偏特化
Base<double,char> b4;//和全特化完全匹配!那么就匹配全特化!
return 0;
}
==如果偏特化更加的合适!那么就会优先去匹配半特化/偏特化!而不是原模板==
偏特化另一个用途——限制参数类型
template<class T1, class T2>
class Base<T1*, T2*>//这是一种更加宽泛的偏特化!是对指针这个类型进行特化!
{
public:
Base()
{
cout << "Data<T1*,T2*>" << endl;
}
};
int main()
{
Base<int, int> b1;
Base<int*, int*> b3;
Base<char*, char*> b4;//只要是指针都会走这个!
return 0;
}
template<class T1, class T2>
class Base<T1&, T2&>
{
public:
Base()
{
cout << "Data<T1&,T2&>" << endl;
}
};
int main()
{
Base<int, int> b1;
Base<int&,int&> b2;
Base<double&, double&> b3;
return 0;
}
==引用也是可以进行偏特化!==
==特化的本质体现了编译器的参数匹配原则==——==只要有这个参数的偏特化那么就优先使用这个参数的偏特化!==
模板的优缺点
【优点】
- 模板复用了代码,节省资源,更快的迭代开发,C++的标准模板库(STL)因此而产生
- 增强了代码的灵活性
【缺陷】
- 模板会导致代码膨胀问题,也会导致编译时间变长
- 出现模板编译错误时,错误信息非常凌乱,不易定位错误
- 对于分离编译支持不好!