C++中typedef的复杂用法很多,特别容易出现在面试题中,这一章用于总结typedef的用法。
本文仅供个人记录和复习,不用于其他用途
typedef的基本用法
typedef与define宏替换不同,它不是简单的文本替换,而是类型替换。我们在开发的过程中,经常会出现类型特别复杂的情况。为了方便,我们通常用typedef进行简化,减少工作量。最简单的用法是用别名替换类型名,比如typedef int* pI。很多时候,我们不一定是为了简化类型名,而是为了给类型名起一个别名,方便我们理解。
扩展的用途
在C程序中,我们实例化struct结构体时,必须用struct + 结构体名 + 变量名的形式,而在C++中则不需要加上struct。那么为了简单一点,可以用typedef简化,这样一来,我们可以直接使用POINT来创建结构体变量:
|
|
另外呢,在实际开发的过程中,可以使用typedef来定义与平台无关的类型。比如在win32平台,int为4个字节,而当处于Linux平台时,int只有2个字节。那么,为了方便起见,可以将int类型起一个别名:
|
|
这样一来,我们在编程的过程中便直接使用INT。当平台中的int类型不再是4个字节时,我们可以使用4个字节的变量来代替它(比如Linux中的long类型),不再需要我们手动一个个地在代码中更改。
复杂声明的替换
事实上,typedef用得最多的还是这个方面。替换时记住一个规则,就是把变量名留到最后,先替换复杂的声明。下面呢,我将举出一些常见的例子:
|
|
这里不是很复杂,直接替换变量名就可以了。
|
|
这个的参数比较复杂,先替换参数,再替换变量名。
|
|
由于指针指向的数组是包含了函数指针,因此先将函数指针替换,再替换变量名。
如何判断一个复杂声明
虽然我上面讲述了如何替换,但大家可能还是不知道,如何判断原来的表达式是什么类型。这里告诉大家一个简单的方法,那就是从变量名开始解读,先往右,碰到括号再往左,然后再跳出括号判断。下面举一些例子:
|
|
从右往左,首先是一个引用,引用的是一个指向int类型的指针。
|
|
func是一个指针,跳出括号,发现是一个函数,那么func是一个函数指针。这个函数的返回值是int类型,参数是指向int类型的指针。
|
|
向右看,func是一个数组,再向左看,这个数组包含的是指针。随后跳出括号,发现是一个函数。那么,func便是函数指针数组。
|
|
不要被这一长串声明吓住了,先看变量名z的右边,很显然这是一个函数,这个函数的参数分别是一个int类型变量和一个函数指针。既然z是函数,那么肯定有返回值。看看左边,明显是一个函数指针。总的来讲,z是一个函数,有两个参数分别为整型变量和函数指针,返回值为函数指针。
注意事项
既然typedef不是简单的文本替换,那么必然会存在一些问题。下面的这个例子很好地说明了这一点:
|
|
按照一般的理解所推断,我们会理所当然的认为const CH就是const char *,事实上这是不正确的。CH所代表的类型是指向char类型的指针,const所作用的是指针而不是所指向的对象,因此,这里const应该是对指针进行了限制。
|
|
另外,上面的声明也是错误的,因为typedef是和auto、extern、mutable、static、register等一样的,都是影响对象的存储特性的类型。尽管typedef并不影响对象的存储,但它确实是这种类型。
typedef和define的区别
翻看了许多资料,我发现了typedef与define的一些不同之处。例如:
|
|
上面的s1、s2、s3都被定义为char *,而s4则定义成了char。从根本上来说,typedef是为类型起别名,而define只是简单的文本替换。