2.10 类型转换
类型转换是将一种类型的值转换为另一种类型的值。
我们曾经指出,表达式a+b中的运算符是一种超载,它可以是定点加,也可以是浮点加。当a和b同为整型,它就是定点加;当a和b同为实型,它就是浮点加。那么,a和b一个是整型,一个是实型时又代表什么加呢?通常,每种语言都会做出自己的规定,使a和b转换成相同的类型(或者同为整型,或者同为实型)。将一个类型的值转换成另一个类型的值,在程序设计中经常出现,通常称为类型转换(Type Conversion)。
类型转换可分为拓展(Widening)和收缩(Narrowing)两类。若转换之前的每一个值都在转换之后的类型中有相应的值,即转换之后的类型值的集合包含转换之前类型值的集合,这样的转换称为拓展,例如整数到实数的转换。反之,若转换之前类型值的集合包含转换之后类型值的集合,则称为收缩,如实数到整数的转换。收缩可能导致某些信息的丢失。在PL/1语言中,由实数到整数的收缩采用截断,而Pascal从实数到整数的转换使用舍入法进行收缩。
在某些语言中,这种类型转换的要求和规则都是隐式的,它由编译器自动生成有关转换代码来实现。这些代码根据对象的类型和语言给出的类型优先规则来确定。例如,FORTRAN类型优先级别是
COMPLEX > DOUBLE PRECISION > REAL > INTEGER
若给定操作a op b,那么在op执行之前,低级的类型向高级的类型转换。一般来说,语言对基本数据类型提供了适当的类型转换,而对复合类型或用户定义类型不提供类型的转换,由程序员自行解决。Pascal中对基本数据类型仅允许从整数到实数的转换,以及子界类型与整数间的拓展与收缩。因此在
var r :real; i :integer; i:=r;
中的赋值语句是非法的,必须以显式的方法写成
i:=frunc(r)
或
i:=round(r)
使实数r截断或舍入成整数后再赋值给整型变量i。
ALGOL 68对类型转换给出了完全的、形式化的隐式转换规则。它一共提出了6种隐式强制转换规则,用以强制将一种类型的值转换到另一种类型的值。这种自动转换削弱了编译器对程序的类型检查能力,因为它使变量的类型说明失去部分作用,掩盖了一些程序员类型使用中的错误。
C++语言允许的类型转换有4种:
标准类型➝标准类型
标准类型➝类类型
类类型➝标准类型
类类型➝类类型
标准类型为除class、struct和union类型(即所有的类类型)外的其他所有类型。对于标准类型,C++提供了两种类型转换:隐式类型转换和显式类型转换。
1.发生隐式转换的情况
混合运算:级别低的类型的值向级别高的类型的值转换;
将表达式的值赋给变量:表达式的值向变量类型的值转换;
实参向形参传值:实参的值向形参的值进行转换;
函数返回结果:返回的值向函数返回类型的值进行转换。
2.显式类型转换
方式为
(1)强制法
(类型名)表达式
或者
(类型名)(表达式)
(2)函数法
类型名 (表达式)
它们都将表达式强制地转换为类型名所代表的类型的值。