c++学习笔记(4.c++中新的关键字)(二)
一:过于粗暴,任何类型之间都可以进行转换,编译器很难判断其正确性。
第二:难于定位,在
源码中无法快速定位所有使用强制类型转换的语句。
补充:在程序设计理论中强制类型转换不被推荐,与goto语句一样,应该进行避免,因为在程序设计过程中,定义变量就应该清楚变量的使用环境,直接定义成有效的类型,避免强制类型转换。还有就是现代的软件产品里面有三个问题是bug的源泉:有运算符的优先级问题、多线程
编程中各个线程的交互、强制类型转换。
c.c++中将强制类型转换分成四个类型:
static_cast类型:用于基本类型间的转换,但不能用于指针类型间的转换。用于有继承关系对象之间的转换和类指针之间的转换。但是static_cast是编译期进行的转换,无法在运行时检测类型,所以类类型之间的转换可能存在风险。代码如下:
[cpp]
#include
int main()
{
int a = 99;
double b = static_cast(a);
printf("%f\n",b);
printf("%c\n",static_cast(b));
getchar();
return 0;
}
const_cast类型:用于去除变量的const属性,注意,它只能去除const int* p或者const int& p这两种类型中的const属性。比如int* const p类型中的const属性是去不掉的,其实不管用什么手段这个const的属性都是去不掉的,int* const p = &a; p一旦指向就不能再改变指向,这其实就是引用的实质!!!
const_cast类型有三个常用环境:第一,去除const int &j;的const只读属性、第二,去除const int * j;的const只读属性、第三,去除const int j;的const只读属性。代码如下:
[cpp]
#include
int main()
{
/*const int &j 去除const属性*/
const int& j = 4;
const_cast(j) = 6; //其实实际上j就是一个只读变量 利用指针也可以改变j的值的
// *(int*)(&j) = 6; //这步的强制类型转换与上面那句代码等效
printf("j is %d\n",j);
int& i = const_cast(j);
i = 12;
printf("j is %d\n",i);
/*const int* p 去除const属性*/
int a = 1;
const int* p = &a;
*const_cast(p) = 2;
// *(int* )p = 2; //与上面代码等效的强制类型转换
printf("*p is %d\n",*p);
/*const int l = 6*/
const int l = 16;
// (int&)l = 17; //与上面语句等效的强制类型转换
// *const_cast(&l) = 17;
// *(int*)&l = 17;
printf("l is %d\n",l);
return 0;
}
对于上面代码有两点要说明:
第一:const_cast其实只读const指针和const引用起作用了,对const常量没有起作用,因为const常量是保存在符号表中的。
第二:对于引用的强制类型转换,int a = 10; (char)a这是将a变量中的值强制类型转换成char类型,切记此时(char)a不是变量不能当做左值使用。但是(char&)a是将a强制类型转换成char类型的引用,其实是一个变量可以当做左值使用!对于const_cast(l) = 17; 来说l常量是存放在符号表中的,而const_cast(l)其实是个有内存空间的变量,其实相当于对l取地址的时候,编译器分配了一个内存空间,这个空间不是用来存放l常量的,而是强制类型转换后这个引用的内存空间,所以说这个17就存放在这个引用的内存空间了!!!
reinterpret_cast类型:用于指针类型间的强制类型转换,用于整数和指针间的强制类型转换,还用于引用间的强制类型转换。(注:此处指针引用的强制类型转换都是没有const属性去除过程的,否则优先使用const_cast)
引用间的强制类型转换(代码如下):
[cpp]
#include
int main()
{
int a = 10;
int &b = a;
char &c = reinterpret_cast(b);
printf("%d\n",reinterpret_cast(b));
a = 129;
printf("a is %d\n",a);
printf("b is %d\n",b);
printf("c is %d\n",c);
return 0;
}
我们仔细说说代码中c引用与b引用的关系,不可否定的是abc三个变量,有其中任何一个变量改变了,都会对另外的两个起到改变的作用!a与b仅仅是名字不同的问题(其余完全相同),但是c引用是与b引用变成char类型引用变量后完全相同的。
reinterpret_cast类型用法,代码如下:
[cpp]
#include
int main()
{
int a = 10;
*reinterpret_cast(&a) = 12;
printf("a is %d\n",a);
int* b = &a;
char* c = reinterpret_cast(b);
*c = 14;
printf("a is %d\n",*c);
return 0;
}
reinterpret_cast是直接从二进制位进行复制,是一种极其不安全的转换。
dynamic_cast类型:主要用于类层次间的转换,还可以用于类之间的交叉转换。dymanic_cast具有类型检查的功能,比static_cast更安全。这个问题等对类有了理解再回来补充。