C++中的typedef语法简介

  根据名字也可以猜测到,typedef这种语法可以用于定义类型,如果某种类型的名称很长,或者未类型增加语义,那么我们就可以考虑使用typedef。看看最简单的例子:

 

1
typedef int INT;

  上面的一行代码就表示INT也能代表int,这条定义可以在Windows头文件中找到。有什么意义呢?这是一种跨平台编译的考虑,看一下另一个Windows头文件中的例子:

 

1
2
3
4
5
#ifndef UNICODE
typedef char TCHAR;
#else
typede wchar_t TCHAR;
#endif

  如果当前环境支持Unicode,那么TCHAR就会等价于wchar_t宽字符类型,否则TCHAR等价于char类型,那么程序员就可以借助TCHAR来隐藏具体的编译环境。

  此外,typedef还可以增强语义,在Windows中所有的句柄本质都是void*类型,而为了增强语义,产生了HWND、HMENU、HBRUSH等不同的类型,让程序可读性增强。

  大多数情况下,typedef是可以用#define来进行替换的,例如:

 

1
#define INT int

不过问题在于,#define只是进行了简单的字符替换,在编译前就被预编译器处理了,而typedef的处理则是编译器行为,因此使用typedef,编译器将能够视INT为一个类型,而不是其他东西。下面还有一个用#define容易引起混淆的例子。

 

1
2
3
4
5
#define pINT int*;
typedef int *pINT2;
 
pINT a, b;
pINT2 c, d;

  一般而言,我们通过类型定义,是希望将pINT定义成一种类型,那么用这种类型进行定义得到的变量,都应该是这种类型。而如果使用#define,那么看起来我们用pINT定义了a和b,实际上只有a是int*,而b只是int。使用typedef很好地避免了这个问题,c和d都是int*类型,这样不至于产生混乱的语义。

  另外,因为typedef不是预编译指令,而被当作语句执行,因此也是有作用域的,typedef的作用域和一般变量相同。冲突的定义会进行覆盖,较晚执行的typedef会覆盖较早执行的typedef。

  最后,typedef还可以用来定义类、结构体、联合体、数组,甚至是函数类型,下面有一个比较全面的代码例子,可以参考注释理解其中的含义:

 

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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#include <iostream>
using namespace std;
 
typedef int* _int, _int2; //_int是int*类型,而_int2是int类型
typedef int INT; //INT是int类型
typedef _int *INT2, *INT3; //INT2和INT3都是*_int类型,也就是**int类型
 
typedef void (*funcptr)(double); //funcptr是一个函数指针类型,指向返回值为void,接受一个double类型参数的函数
 
typedef union {
    char c;
    int i;
    bool b;
} Foo; //Foo是一个联合体
 
typedef class TestClass {
    int a, b, c;
public:
    TestClass(int a, int b, int c) : a(a), b(b), c(c) {
    }
} TESTCLASS; //TESTCLASS就是TestClass类
 
void hello(double x) { //funcptr可以指向这个函数
    cout << x << endl;
}
 
int main() {
    INT a = 6;
    _int2 e = 7;
    _int c = &a;
    INT2 b = &c;
    INT3 d = &c;
    cout << a << e << *c << **b << **d << endl;
 
    funcptr p = hello;
    p(3.333);
    cout << p << endl;
 
    Foo foo;
    foo.i = 65;
    cout << foo.b << foo.c << foo.i << endl;
 
    TESTCLASS tc(1, 2, 3);
 
    system("pause");
    return 0;
}