跳至主要內容

类模板

LincZero大约 3 分钟

类模板

类模板

使用

使用

  • 简概
    • C++最初不支持模板,但模板被引入后一直在改进,因此有的编译器可能不支持所有特性
    • 模板提供参数化类型parameterized type
  • 使用场景
    • 可以用于设计容器类(container calss)(如Stack、Queue等)
  • 使用
    • 和模板函数差不多,但稍复杂些
    • 一方面,在class声明前加template <typename T>
    • 另一方面,所有的成员函数前加template <typename T>,并把作用域解析符前的类名换成类名<T>
  • 原理
    • 和模板函数差不多
    • 当定义类实例时,会根据类名<T>模板来生成不同的类声明和和类方法
    • 因为是模板,所以可以不用(不会产生定义)也不能(模板不能单独编译)分离头文件和实现,实现要写在头文件中
  • 类模板的函数模板区别
    • 与函数模板不同,必须显式提供所需的类型而不能由参数类型来确定要生成那种函数

类型参数补充

  • 类型参数
    • template <typename T>中的T是一个类型参数type parameter
    • 这这意味着它类似于变量,T可以修改名字的变量名,而赋值给它的是类型
  • 非类型(non-type)参数或表达式(expression)参数
    • template <int n>中的n是一个非类型参数non-type parameter)或表达式参数expression parameter
    • 比如template <class T, int n>可以替换为
  • 类模板传参和构造函数传参区别(以创建数组为例)
    • vector类型使用的是构造函数方法
      • 优点:通过new和delete管理堆内存,更方便
    • array类型使用的是类模板传参方法
      • 优点:为自动变量维护内存栈,速度更快
      • 缺点:会为不同长度的数组生成多个模板定义。如Array<int, 2>;Array<int, 3>;会生成两个定义

功能多样性 / 功能扩展

模板功能性多,可用作基类、组件类、还可用作其他模板的类型参数

  • 可以递归使用模板
    • Array<Array<int,5>,10> twodee;,这相当于二维数组int twodee[10][5];
  • 可以使用多个类型参数
    • template <class T1, class T2>
  • 默认类型模板参数
    • template <class T1, class T2=int> class A {...}

具体化、实例化

具体化specialization)和实例化instantiation

写法和函数模板的不太同,主要原因可能是因为:

  • 函数模板在圆括号的参数中写类型参数,而且会自动判别类型
  • 类模板的原括号保留用作构造函数,使用尖括号,而且是显式写出类型

隐式实例化(implicit instantiation

  • 写法
    • 举例:假如定义了template <class T> class A {...},则当声明对象A<int> a;时进行隐式实例化

显式实例化(explicit instantiation

  • 写法
    • 举例:假如定义了template <class T> class A {...},则可以template class A<int>;进行显式实例化

显式具体化(explicit specialization

  • 简概

    • 是特定类型(用于替换模板中的泛型)的定义
  • 使用场景

    • 需要为特殊类型实例化时,对模板进行修改,使其行为不同
  • 写法

    • 通用:template <> class ClassName <specialized-type-name> {...};

      或:calss ClassName<specialized-type-name> {...};(早期的写法)

    • 举例:template <> class A <int> {...};

部分具体化(partial specialization

  • 简概
    • 即限制模板的通用性
  • 写法
    • 举例:template <class T1> class A <T1, int> {...};,该语句将T2具体化为int,但T1保持不变

功能扩展

嵌套 x 模板