4.11.2 其他隐式类型转换
除了算术转换之外还有几种隐式类型转换,包括如下几种。
数组转换成指针:在大多数用到数组的表达式中,数组自动转换成指向数组首元素的指针:
- int ia[10]; // 含有10个整数的数组
- int* ip = ia; // ia转换成指向数组首元素的指针
当数组被用作decltype关键字的参数,或者作为取地址符(&)、sizeof及typeid(第19.2.2节,826页将介绍)等运算符的运算对象时,上述转换不会发生。同样的,如果用一个引用来初始化数组(参见3.5.1节,第114页),上述转换也不会发生。我们将在6.7节(第247页)看到,当在表达式中使用函数类型时会发生类似的指针转换。
指针的转换:C++(www.cppentry.com)还规定了几种其他的指针转换方式,包括常量整数值0或者字面值nullptr能转换成任意指针类型;指向任意非常量的指针能转换成void*;指向任意对象的指针能转换成const void*。15.2.2节(第597页)将要介绍,在有继承关系的类型间还有另外一种指针转换的方式。
转换成布尔类型:存在一种从算术类型或指针类型向布尔类型自动转换的机制。如果指针或算术类型的值为0,转换结果是false;否则转换结果是true:
- char *cp = get_string();
- if (cp) /* . . . */ // 如果指针cp不是0,条件为真
- while (*cp) /* . . . */ // 如果*cp不是空字符,条件为真
转换成常量:允许将指向非常量类型的指针转换成指向相应的常量类型的指针,对于引用也是这样。也就是说,如果T是一种类型,我们就能将指向T的指针或引用分别转换成指向const T的指针或引用(参见2.4.1节,第61页和参见2.4.2节,第62页):
- int i;
- const int &j = i; // 非常量转换成const int的引用
- const int *p = &i; // 非常量的地址转换成const的地址
- int &r = j, *q = p; // 错误:不允许const转换成非常量
相反的转换并不存在,因为它试图删除掉底层const。
类类型定义的转换:类类型能定义由编译器自动执行的转换,不过编译器每次只能执行一种类类型的转换。在7.5.4节(第295页)中我们将看到一个例子,如果同时提出多个转换请求,这些请求将被拒绝。
我们之前的程序已经使用过类类型转换:一处是在需要标准库string类型的地方使用C风格字符串(参见3.5.5节,第124页);另一处是在条件部分读入istream:
- string s, t = "a value"; // 字符串字面值转换成string类型
- while (cin >> s) // while的条件部分把cin转换成布尔值
条件(cin>>s)读入cin的内容并将cin作为其求值结果。条件部分本来需要一个布尔类型的值,但是这里实际检查的是istream类型的值。幸好,IO库定义了从istream向布尔值转换的规则,根据这一规则,cin自动地转换成布尔值。所得的布尔值到底是什么由输入流的状态决定,如果最后一次读入成功,转换得到的布尔值是true;相反,如果最后一次读入不成功,转换得到的布尔值是false。