zmqNut

明知会散落, 仍不惧盛开

0%

模板中class与typename的区别

电脑壁纸6ea2d6a14571a394a7ba914feedda21a6d7d4d0a_raw

相同之处

一般对模板参数类型typenameclass认为是一样的. 这两者在参数类型中确实是一样的,以下两种定义都行。

1
2
template<class T> 
class A {};
1
2
template<typename T>
class A {};

两者typenameclass参数类型中没有不同。

为什么定义这两个符号呢?

  1. 最开始定义定义模板的方法就是template<class T> , 但是class毕竟都认为是一个类, 在使用时难免会有些点混淆, 也就定义了typename来标志参数类型
  2. 最重要关于 typename可以使用嵌套依赖类型, 也就是类型可以嵌套使用. 这也是两个的不同之处。

不同之处

typename可以用在嵌套依赖中, 并且表示其类型, 而class并没有这样的功能.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include<iostream>
using namespace std;
template<class T>
class people {
public:
typedef T value_type;
typedef T* pointer;
typedef T& reference;
};

template<class T>
struct man {
public:
typedef typename T::value_type value_type;
typedef typename T::pointer pointer;
typedef typename T::reference reference;
void print() {
cout << "man" << endl;
}
};

int main() {
man<people<int>> Man;
Man.print();
}

typename可以嵌套使用,

typename告诉编译器这不是一个函数, 也不是一个变量而是一个类型. 这里使用typedef又将参数类型重新定义一次,增加了一层间接性,使用的时候也不需要在写很长的代码

这里typename是对people类中定义的类型进行了一次提取, 这里将typename改为class就会出错。

typename主要的作用

对于模板参数是类的时候, typename能够提取出该类所定义的参数类型.

并不是所有的嵌套依赖类型都要加上typename, 有一个例外 : 当继承列表或成员初始化列表中对基类进行初始化的时候, 可以去掉typename关键字

1
man(int x) : T::value_type(x) {}

总结:

  1. typenameclass在作为参数类型时用法一样, 没有区别
  2. typename主要用于对嵌套依赖类型进行提取(萃取). 而class没有这样的功能.
  3. typename提取的一个例外是在继承或成员初始化列表中对基类进行初始化时不用加typename关键字

转载于:https://blog.csdn.net/Function_Dou/article/details/84644963

---------- End~~ 撒花ฅ>ω<*ฅ花撒 ----------