今天我们来聊聊C++的类型别名。
如今,定义类型别名有两种定义方法:
//第一种 typedef int ZHENGSHU;
这里可以看到,typedef 关键字后面声明了一个 int 类型的别名 ZHENGSHU,在之后的定义中,ZHENGSHU 将起到和 int 相同的效果。
//第二种 using zheng_shu = ZHENGSHU;
使用了 using 关键字,将 zheng_shu 定义为 ZHENGSHU 类型的别名,作用与第一种类似。
《C++ Primer》第五版中特意写道,当const与复合类型的别名复合使用时,代码也许会出现意想不到的结果。
比如以下代码:
//typedef类型别名定义,pstring等价于char指针类型 typedef char* pstring;
此时,pstring 类型为一个 char* 类型,它是 char 类型和其指针类型的复合类型。
因此,当在 pstring 前面加上 const 时,事情就变得不那么简单了:
//定义pstring底层常量c3, 底层指针c4 const pstring c3 = 0; const pstring *c4; //此时报错,显示“表达式必须是可修改的左值” //意味着c3现在为一个顶层的常量指针 c3 = c4;
熟悉 const 的大家一定都清楚,const 写在类型前面时,是一个底层 const 定义。
而 pstring 本身是一个 char* 类型,在前面的基础上,它需要指向一个 char 类型的指针常量。
此时c4为一个指向 pstring 类型指针的指针。
而在IDE中写下此段代码后,c3下面会弹出错误标识,提示你c3是一个不能修改的值。
这个时候就很奇怪了,为什么我用底层 const 定义出的指向常量的指针变成了一个常量指针?
而与此同时,用 char 类型复写一段同样的代码,就不会报错。
//定义char指针c1,char常量d,char指针c2,均为底层const变量 const char* c1 = 0; const char d = 'a'; const char* c2 = &d; //可以看到,c2可以直接向c1赋值 c1 = c2;
这里的c2是可以直接向c1进行赋值的,也意味着c1是可修改的。
那么,pstring 字段究竟发生了什么?
其实原书中给出了对应的解释:声明中用到pstring时,其基本数据类型是指针。可是用 char* 重写声明语句后,数据类型就变成了 char,*成为了声明符的一部分。
在改写后的代码中,const char 成了基本数据类型。因此,c1可以看做是一个指向 char 类型常量的指针。
而c3则作为一个 pstring 类型的常量被定义,这个定义等价于:
const int i = 1;
只是 int 类型是一个数据类型,而 pstring 则是一个指针类型。
当我们理解原理后,再回过头来细品这个问题,就能够品味到C++语言中无处不在的细节。
希望这篇文章能帮助你更好理解这两个字段的复合使用~