typedef 和 typename 区别

typedef关键字用法:

在C/C++语言中,typedef常用来定义一个标识符及关键字的别名,它是语言编译过程的一部分,但它并不实际分配内存空间,实例像:

typedef    int       INT;
typedef    int       ARRAY[10];
typedef   (int*)   pINT;

typedef可以增强程序的可读性,以及标识符的灵活性,但它也有“非直观性”等缺点。

引入typedef的目的是:

为了隐藏特定类型的实现,强调使用类型的目的。

简化复杂的类型定义,使其更易理解。

允许一种类型用于多个目的,同时使得每次使用该类型的目的明确。

四个用途

用途一:

定义一种类型的别名,而不只是简单的宏替换。可以用作同时声明指针型的多个对象。比如:
char* pa, pb; // 这多数不符合我们的意图,它只声明了一个指向字符变量的指针, 
// 和一个字符变量;
以下则可行:
typedef char* PCHAR; // 一般用大写
PCHAR pa, pb; // 可行,同时声明了两个指向字符变量的指针
虽然:
char *pa, *pb;
也可行,但相对来说没有用typedef的形式直观,尤其在需要大量指针的地方,typedef的方式更省事。

用途二:

用在旧的C的代码中帮助struct。声明struct新对象时,必须要带上struct,即形式为: struct 结构名 对象名,如:

[cpp] view plain copy 

  1. struct tagPOINT1  
  2. {  
  3.     int x;  
  4.     int y;  
  5. };  
  6. struct tagPOINT1 p1;   

而在C++中,则可以直接写:结构名 对象名,即:

tagPOINT1 p1;

typedef定义之后如下所示

[cpp] view plain copy 

  1. typedef struct tagPOINT  
  2. {  
  3.     int x;  
  4.     int y;  
  5. }POINT;  
  6. POINT p1; // 这样就比原来的方式少写了一个struct,比较省事,尤其在大量使用的时候  

用途三:

用typedef来定义与平台无关的类型。
比如定义一个叫 REAL 的浮点类型,在目标平台一上,让它表示最高精度的类型为:
typedef long double REAL; 
在不支持 long double 的平台二上,改为:
typedef double REAL; 
在连 double 都不支持的平台三上,改为:
typedef float REAL; 
也就是说,当跨平台时,只要改下 typedef 本身就行,不用对其他源码做任何修改。
标准库就广泛使用了这个技巧,比如size_t。
另外,因为typedef是定义了一种类型的新别名,不是简单的字符串替换,所以它比宏来得稳健。

用途四:

为复杂的声明定义一个新的简单的别名。方法是:在原来的声明里逐步用别名替换一部分复杂声明,如此循环,把带变量名的部分留到最后替换,得到的就是原声明的最简化版。举例:

1. 原声明:int *(*a[5])(int, char*);
变量名为a,直接用一个新别名pFun替换a就可以了:
typedef int *(*pFun)(int, char*); 
原声明的最简化版:
pFun a[5];

2. 原声明:void (*b[10]) (void (*)());
变量名为b,先替换右边部分括号里的,pFunParam为别名一:
typedef void (*pFunParam)();
再替换左边的变量b,pFunx为别名二:
typedef void (*pFunx)(pFunParam);
原声明的最简化版:
pFunx b[10];

3. 原声明:doube(*)() (*e)[9]; 
变量名为e,先替换左边部分,pFuny为别名一:
typedef double(*pFuny)();
再替换右边的变量e,pFunParamy为别名二
typedef pFuny (*pFunParamy)[9];
原声明的最简化版:
pFunParamy e;

 

typename关键字用法:

在C++中typename一般用来声明模板的模板参数(template parameter):

template<typename T> class X;   //T是一个模板参数

typename的使用场合

(1)用在模板定义里, 标明其后的模板参数是类型参数

2模板中标明“内嵌依赖类型名”

内嵌是指定义在类名的定义中的。

依赖是指依赖于一个模板参数。

类型名是指这里最终要指出的是个类型名,而不是变量。例如iterator_traits::difference_type完全有可能是类iterator_traits 类里的一个static对象。而且当我们这样写的时候,C++默认就是解释为一个变量的。所以,为了和变量区分,必须使用typename告诉编译器。
不是所有的T::type_or_variable, 或者tmpl:type_or_variable都需要使用typename的,有以下两个例外。

例外

(1)类模板定义中的基类列表。

(2)类模板定义中的初始化列表。

这里不用typename是因为编译器知道这里需要的是类型还是变量,(1)基类列表里肯定是类型名,(2)初始化列表里肯定是成员变量名。

typename在下面情况下禁止使用:

模板定义之外,即typename只能用于模板的定义中

非限定类型,比如前面介绍过的intvector之类

基类列表中,比如template : T::InnerType不能在T::InnerType前面加typename

构造函数的初始化列表中

如果类型是依赖于模板参数的限定名,那么在它之前必须加typename(除非是基类列表,或者在类的初始化成员列表中)

其它情况下typename是可选的,也就是说对于一个不是依赖名的限定名,该名称是可选的,例如vector vi;

 

你可能感兴趣的:(typedef 和 typename 区别)