【C++程序设计原理与实践 — 读书笔记】
类型安全
每个对象再定义时都会被分配一个类型。
对于一个程序或程序的一个部分,如果使用的对象符合他们规定的类型,那么他们是类型安全的。
但是,存在很多使用方式,导致类型不安全:如:在一个变量没有初始化之前使用它,则认为他不是类型安全的:
int main(){
double x; // x 未初始化
double y = x; // x 未定义 => y 未定义
double z = 2.0 + x; // x 未定义 => z 未定义
}
记住:初始化变量是一个好习惯,这会为我们减少很多麻烦!!!
类型安全的思想在编写代码时非常重要。
安全类型转换
C++内部提供了一些隐式的类型转换,可以帮助我们做一些明知不可为而为之的事情,当然,这种做法也是更加方便和有效的。
例如:
char c = 'x'; //
int i1 = c; // i1 = 120;(字符'x'在ASCII中的数值)
int i2 = 'x'; // i2 = 120;
char c2 = i1;
cout << c << ' ' << i1 << ' ' << c2 << '\n'; // 打印:x 120 x
在这种情况下,一个值总是被转换成一个等价的值,或者一个最接近等价的值(对于 double),那么这些转换就是安全的:
● bool => char
● bool => int
● bool => double
● char => int
● char => double
● int => double
最常用的转换是从 int 到 double,正是由于这种特性,C++允许在表达式中混用 int 和 double:
double d1 = 2.3;
double d2 = d1 + 2;
if(d1 > 0){
error("d1 is nefative");
}
注:一些计算机中,当一个很大的整数转换成 double 时,我们可能要承受一些精度上的损失。(这种情况并不常见)
不安全类型转换
但是,当我们在进行一些隐性转换时,一个值可以转换成一个与其原始值不相等的值。
int main(){
int a = 20000;
char c = a;
int b = c;
if(a != b){
cout << "oops!:" << a << "!=" << b << "\n";
}else{
cout << "Wow!We have large characters\n";
}
}
上述这种转换被称为“缩小”转换,用一个较小的对象存储一个较大的值。
当用 char 来存储 int 类型数据时,一个 int 的数据往往都会比一个 char 大,这种情况下,它可以保存一个 int 类型的数据,但是这个值并不能表示为一个 char(一个有效的 char)。
常见的不安全的类型转换:
● double => int
● double => char
● double => bool
● int => char
● int => bool
● char => bool
但是,这些转换是被编译器所接受的,即使他们是不安全的。
常见的问题 1:
double x = 2.7;
……
int y = x; // y = 2
在我们定义 y 时可能忘记了 x 是一个 double,或者我们临时忘记了 double 到 int 转换会截断(总是去掉小数点后的尾数),而不是使用常用的四舍五入。发生的事情完全的可以预测的,但是在int y = x;处没有任何东西能提醒我们信息(.7)被丢掉了。
常见的问题 2:不是所有的 int 都有等价的 char
int a = 1000;
char b = a; // b = -24;(和硬件相关)
char 的取值范围:[-128,127],但是只有 [0,127] 是可以方便移植的。(不同的计算机对于 char 的类型可能不同)
缩少转换的历史问题:
继承于 C 语言,并且有很多代码依赖于缩小转换。这种转换在实际使用中,如果通过合理的限制,这些不安全的转换在一些小的程序中是可管理的,但是在大的程序中可能是错误的来源。