0%

C++ 模板中 typename 与 class 关键字区别

两种方式都可以在模板中使用,但是它们有什么区别呢

我们都知道,在 STL 中基本上都使用了模板类的声明,即 template. 在模板类的声明中,我们有两种方式:

1
2
template <class T>
template <typename T>

在这里,class 和 typename 是相同的。也就是说,在声明一个 template type parameter (模板类型参数) 的时候,class 和 typename 意味着

完全相同的东西.

但是,在 C++ 中,有的时候必须要使用 typename. 下面我们列举下面一个例子.

关键字 typename 被用来作为型别之前的标识符号.

1
2
3
4
5
template <class T>
class MyClass{
typename T::SubType * ptr;
...
};

在这里,typename 指出 SubType 是 class T 中定义的一个类别,因此 ptr 是一个指向 T::SubType 型别的指针。如果没有关键字 typename, SubType 会被当成一个 static 成员,于是

1
T::SubType * ptr

会被解释为型别 T 内的数值 SubType 与 ptr 的乘积.

SubType 成为一个型别的条件是,任何一个用来取代 T 的型别, 其内部必须有一个内部型别 (inner type) SubType 的定义。例如,将型别 Q 当作 template 的参数.

MyClass x;

必要条件是型别 Q 有如下的内部型别定义:

1
2
3
4
class Q{
typedef int SubType;
...
};

因此,MyClass 的 ptr 成员应该变成一个指向 int 型别的指针,子型别 SubType 也可以成为抽象

数据型别(例如,class):

1
2
3
4
class Q{
class SubType;
...
};

注意,如果要把一个 template 中的某个标识符号指定为一种类别, 就算是意图显而易见,关键字 typename 也是不能省略的,因此 C++ 的一般规则是,除了使用 typename 修饰之外,template 内的任何标识符号都被视为一个值而不是一个类别 (对象).

总结:

  1. template 与 template 一般情况下这两个通用, 但有一个特例,就是当 T 是一个类,而这个类又有子类 (假设名为 innerClass) 时,应该用 template:
  2. typename T::innerClass myInnerObject; 这里的 typename 告诉编译器, T::innerClass 是一个类,程序要声明一个 T::innerClass 类的对象, 而不是声明 T 的静态成员,而 typename 如果换成 class 则语法错误.