非类型模板参数与模板特化

目录

  • 1. 非类型模板参数
  • 2. 模板的特化
    • 2.1 函数模板的特化
    • 2.2 类模板的特化
    • 2.3 全特化与半特化
    • 2.4 模板的分离编译
      • 2.4.1 为什么模板不支持分离编译
    • 2.5 解决方法
    • 2.6 模板的优缺点
      • 2.6.1 优点
      • 2.6.2 缺点

1. 非类型模板参数

之前由于一个类,我们想让里面的参数类型不同,引入了模板,不用重复写冗余的代码。
现在有一个静态顺序表,其大小示固定的,假如想让他变化,碰见了和之前类似的问题。
非类型模板参数与模板特化_第1张图片
其实也可以用模板解决,size_t N=100,他是一个非类型的常量,确实,不是常量他也不可能做数组的大小。
注意:

非类型模板参数与模板特化_第2张图片
不过通常不用静态的顺序表,栈只有8M。
注意:

  1. 非类型模板参数是一个常量
  2. 浮点数、类对象以及字符串是不允许作为非类型模板参数的。
  3. 非类型的模板参数必须在编译期就能确认结果。

2. 模板的特化

2.1 函数模板的特化

非类型模板参数与模板特化_第3张图片

对于自定义类型,比较出来是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;
}

模板特化要注意:

  1. 必须要先有一个基础的函数模板
  2. 关键字template后面接一对空的尖括号<>
  3. 函数名后跟一对尖括号,尖括号中指定需要特化的类型
  4. 函数形参表: 必须要和模板函数的基础参数类型完全相同,如果不同编译器可能会报一些奇怪的错误。
    可以看到上面函数模板的特化还是比较复杂的,还不如自己不用模板写的第一个函数,反正你特化也要重新写,第一个函数还比你的简单易读。所以一般情况下如果函数模板遇到不能处理或者处理有误的类型,为了实现简单通常都是将该函数直接给出。

2.2 类模板的特化

上面提到,函数模板的特化复杂,还不如自己直接写的一个函数简单易读,但是类模板可以吗。

template<class T1,class T2>
class Date{
public:
	Date()
	{
		cout << "Date(T1,T2)" << endl;
	}
private:
	T1 _year;
	T2 _day;
};
Date<int,double> d1;

这是一个类模板,实例化后,一切正常。那么问题来了假如想要一个专属于double的类模板呢?
非类型模板参数与模板特化_第4张图片

可以看到,想模仿上面对于函数模板的例子,直接对他写一个类,是不行的,所以只能走那个麻烦一点的特化。
非类型模板参数与模板特化_第5张图片

2.3 全特化与半特化

上面那中就是全特化,直接全部指定为double类型

半特化:
不是特化一半,是特化一部分。

让一部分自定义,一部分指定
非类型模板参数与模板特化_第6张图片
并不是说一定要是数据类型,也可以是一个指针或者引用。
非类型模板参数与模板特化_第7张图片

2.4 模板的分离编译

分离编译,将代码模块化,方便阅读代码,易于维护管理,提高编译效率。
怎么提高的呢?
你写到一块的时候,假如要修改代码,要重新编译,效率就低了。分离编译,假如要修改某个.o文件的代码,然后编译器根据修改时间,然后重新编译刚才修改的文件重新生成.o,除此之外代码的可读性也得到了大大提升

但是呢,模板是不支持分离编译的。

2.4.1 为什么模板不支持分离编译

非类型模板参数与模板特化_第8张图片
当由于模板在实例化之前是不会生成代码的,test.cpp中没有使用然后不会生成代码,所以main.cpp中拿到的函数名,在连接过程中通过符号表找不到对应的地址,自然就链接错误了。
非类型模板参数与模板特化_第9张图片
当然类模板也同样如此,类本质就是访问他的成员函数。

2.5 解决方法

1.声明定义同时放在一个.h文件中,这样另一个文件包含的时候,将他的文件也展开了。
2.模板的定义位置显示实例化

2.6 模板的优缺点

2.6.1 优点

  1. 模板增强了代码的复用性、节省资源、更快的迭代开发,C++的标准模板库(STL)也因此而产生
    C++98才出现的模板,有了模板之后才出现的STL库

  2. 增强了代码的灵活性
    比如,相同的函数接口,只是传入的参数类型不一样,只需要传入不同的参数,即可以实例化不同的模板代码

2.6.2 缺点

  1. 模板会导致代码膨胀问题,也会导致编译时间边长
    我们知道使用模板时, 同一模板生成不同的模板实类后会是多份代码

  2. 模板在实例化的时候,就会使得比不用模板时的时间稍长

  3. 出现模板编译错误的时候,错误信息非常凌乱,不易定位错误

你可能感兴趣的:(Cpp,c++,指针)