模板的进阶

Posted 两片空白

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了模板的进阶相关的知识,希望对你有一定的参考价值。

目录

一.非类型模板参数

二.模板的特化

2.1 函数模板的特化

 2.2 类模板特化

2.2.1 全特化

2.2.2 偏特化 

三.模板分离编译 

3.1 什么是分离编译

3.2模板分离编译

 四.模板总结


一.非类型模板参数

模板的参数分为类型模板参数和非类型模板参数

  • 类型模板参数:出现在模板参数列表中,跟在class或者typename之类的参数类型名称。
  • 非类型形参:就是用一个常量作为类或者函数模板的一个参数,在类或函数模板中可将该参数当作常量来使用。

 注意:

  1.  非类型参数在函数或者类模板中被当作常量使用。
  2. 浮点数,类对象以及字符串是不允许作为非类型模板参数。基本上整形参数比较多。
  3. 非类型模板参数必须在编译期就能确定结果。

二.模板的特化

一般情况下,使用模板可以实现一些与类型无关的代码,但是对于一些特殊类型的,可能会得到一个错误的结果。

 此时就需要对模板进行特化,

定义:在原函数模板的基础上,针对特殊类型所实现的特殊化实现方式。

2.1 函数模板的特化

函数模板特化步骤:

  • 必须先有一个基础的函数模板
  • 关键字template后跟一对空的尖括号<>
  • 函数名后面跟一对尖括号<>,尖括号里指定需要特化的类型。
  • 函数中使用模板参数类型的必须和模板函数的基础参数类型对应且完全相同。(即使用T1位置替换成T1特化的类型,使用T2位置替换成T2特化的类型......)

上述代码就可以这样写:

 但是一般情况下函数模板遇到不饿能处理或者处理有误的类型,为了实现简单都是直接将对应类型函数直接写出。

 2.2 类模板特化

类函数模板特化步骤:

  • 必须先有一个基础的类模板
  • 关键字template后跟一对空的尖括号<>
  • 类名后面跟一对尖括号<>,尖括号里指定需要特化的类型。
  • 类中使用模板参数类型的必须和模板类的基础参数类型对应且完全相同。(即使用T1位置替换成T1特化的类型,使用T2位置替换成T2特化的类型......)

2.2.1 全特化

全特化就是将模板参数列表中的所有参数都确定化

2.2.2 偏特化 

偏特化:指将模板参数进一步进行条件限制的版本。

对于下面代码:

 偏特化两种表现形式:

  • 部分特化

将模板参数类的类型部分特化。

  •  参数加限制条件

类型加限制条件

如何让调用:

三.模板分离编译 

3.1 什么是分离编译

在实际项目工程中,一般将函数或者类的声明放到头文件中,将函数或者类的定义放到源文件中。所以一个项目可能含有多个源文件和头文件。但是每个源文件单独编译生成目标文件,最后将所有目标文件链接起来生成单一的可执行文件的过程称为分离编译。

3.2模板分离编译

模板分离编译,就是模板的声明和定义分离开,在头文件进行声明,在源文件中完成定义。

结论:模板的声明和定义是不能分离的。 

原因:

C/C++程序要运行必须通过四个阶段,预处理,编译,汇编,和链接。

这个错误发生在链接时。

源文件通过预处理,编译和汇编后生成目标文件,上面源文件生成main.o,Add.o文件。但是每个源文件生成的目标文件是独立的。​​​​​​​因为main.o和Add.o文件是独立的,Add.o文件的模板并不知道模板参数的类型,无法生成相应函数。 当链接时通过main函数调用Add函数,就找不到Add函数的定义。

总的来说就是:main.o文件不知道Add函数的定义,Add.o不知道模板类型,无法生成函数定义。

解决办法:

  • 将声明和定义放到一个文件中,放到相应头文件中。

  • 在模板定义位置显示实例化(不推荐)

 四.模板总结

优点:

  • 模板复用了代码,节省资源,更快的迭代开发,C++标准库在此基础上产生的。
  • 增强代码灵活性

缺点:

  • 模板导致代码膨胀,也会导致编译时间变长(实例化函数需要时间)
  • 出现模板错误,不好定位错误位置。

以上是关于模板的进阶的主要内容,如果未能解决你的问题,请参考以下文章

C++模板进阶

C++模板进阶

C++模板进阶

C++——模板进阶

模板的进阶

C++初阶:模板进阶非类型模板参数 | 模板的特化 | 模板分离编译