之前由于一个类,我们想让里面的参数类型不同,引入了模板,不用重复写冗余的代码。
现在有一个静态顺序表,其大小示固定的,假如想让他变化,碰见了和之前类似的问题。
其实也可以用模板解决,size_t N=100,他是一个非类型的常量,确实,不是常量他也不可能做数组的大小。
注意:
对于自定义类型,比较出来是0,对于字符串应该是相等的,结果不相等。
说明这个函数模板对于字符串来说不适用,必须要针对他特殊化一个函数。
平常对于字符串是这样比较的
bool IsEqual(const char* p1, const char* p2)
{
if (strcmp(p1, p2) > 0)
{
return true;
}
return false;
}
即使有模板,也会优先匹配自己写的函数。
但是针对模板,他有自己的特化
模板是引用,你也必须是引用,但是加了引用还要保证指针不能被修改,指针前面要在加const
//形参p1是外面p1的引用,不能修改外面的数组名,所以p1前面也要加const
template<>
bool IsEqual<const char*& const>(const char*& const p1,const char*& const p2)
{
if (strcmp(p1, p2) > 0)
{
return true;
}
return false;
}
模板特化要注意:
上面提到,函数模板的特化复杂,还不如自己直接写的一个函数简单易读,但是类模板可以吗。
template<class T1,class T2>
class Date{
public:
Date()
{
cout << "Date(T1,T2)" << endl;
}
private:
T1 _year;
T2 _day;
};
Date<int,double> d1;
这是一个类模板,实例化后,一切正常。那么问题来了假如想要一个专属于double的类模板呢?
可以看到,想模仿上面对于函数模板的例子,直接对他写一个类,是不行的,所以只能走那个麻烦一点的特化。
上面那中就是全特化,直接全部指定为double类型
半特化:
不是特化一半,是特化一部分。
让一部分自定义,一部分指定
并不是说一定要是数据类型,也可以是一个指针或者引用。
分离编译,将代码模块化,方便阅读代码,易于维护管理,提高编译效率。
怎么提高的呢?
你写到一块的时候,假如要修改代码,要重新编译,效率就低了。分离编译,假如要修改某个.o文件的代码,然后编译器根据修改时间,然后重新编译刚才修改的文件重新生成.o,除此之外代码的可读性也得到了大大提升
但是呢,模板是不支持分离编译的。
当由于模板在实例化之前是不会生成代码的,test.cpp中没有使用然后不会生成代码,所以main.cpp中拿到的函数名,在连接过程中通过符号表找不到对应的地址,自然就链接错误了。
当然类模板也同样如此,类本质就是访问他的成员函数。
1.声明定义同时放在一个.h文件中,这样另一个文件包含的时候,将他的文件也展开了。
2.模板的定义位置显示实例化
模板增强了代码的复用性、节省资源、更快的迭代开发,C++的标准模板库(STL)也因此而产生
C++98才出现的模板,有了模板之后才出现的STL库
增强了代码的灵活性
比如,相同的函数接口,只是传入的参数类型不一样,只需要传入不同的参数,即可以实例化不同的模板代码
模板会导致代码膨胀问题,也会导致编译时间边长
我们知道使用模板时, 同一模板生成不同的模板实类后会是多份代码
模板在实例化的时候,就会使得比不用模板时的时间稍长
出现模板编译错误的时候,错误信息非常凌乱,不易定位错误