在C语言中,如果赋值运算两边类型不同,则会发生类型转换。一般来说,C语言有两种形式的类型转换:隐式转换和显式转换。
隐式转换,就是编译器自动根据其类型,将其转换成另一个适合赋值的恰当类型。
显式转换,则是需要咱手动写出应该转换成哪一种类型,然后根据指定的类型强制转换。
但是,这些转换都是编译器最底层在做的事情,就算我们通过调试,也难以发现编译器到底做了什么样的转换,转换成了什么类型,具体的值是多少,程序出错也无从查起。所以,C++中诞生了四种新的类型转换:
static_cast,静态转换。看名字很不好理解其作用是什么,但是其功能很简单——所有编译器进行的隐式类型转换,都叫做static_cast。比如从int转换成double,从地址转换成int,这些不需要我们特意去写出转换类型的,都直接用static_cast,让编译器去自动转换。
int main()
{
int i = 1;
double d = static_cast<int>(i);
//这里自动将i的值转换成了对应double的值,然后传递给d
cout << d << endl;
}
reinterpret_cast,重新解释的转换。我们都知道,double相对于int,是精度更高的数据类型,int转换成double是从低向高的转换。但是如果double转换成int,则是从高向低的转换,此时便需要用reinterpret_cast来解决这一问题。
int main()
{
double d = 12.34;
int a = static_cast<int>(d);
cout << a << endl;
// 这里使用static_cast会报错,应该使用reinterpret_cast
//int *p = static_cast<int*>(a);
int* p = reinterpret_cast<int*>(a);
return 0;
}
const_cast,常属性转换。但是他的目的可不是将变量赋值为常属性,而是删除变量的常属性。?
比如以下程序
int main()
{
const int a = 2;
int& p = a;//在此报错
p = 3;
}
正常来说,如果我们对一个const进行非const引用,属于权限的放大,程序会报错。但是,我们可以通过const_cast来删除他的const属性。
int main()
{
const int a = 2;
int& p = const_cast<int&>(a);
//const_cast必须传入指针或者引用
p = 3;
}
此时便可以正常引用,且可以通过p修改a的值。但是只有p的值才可以修改,a仍是const无法修改!
但是,当我们分别输出a和p的值时,会发现一个神奇的事情:
?而在const int a前加上关键字volatile,输出结果又一样了
正常情况下,如果一个值已经被赋予了const属性,编译器在访问其值的时候,便不会访问其具体地址上的内存,而是会事先用一块空间专门存这些常量,等到访问的时候直接输出常量。因此,编译器并不会考虑还会出现const也会被修改的情况。而volatile,不稳定的,表示这个const并不是稳定的,强制编译器每一次都要去访问内存来调用那里的值。
dynamic_cast,动态转换,用于将父类对象转化为子类对象。
我们都知道,子类对象可以直接赋值给父类对象,原理是切片,就是直接将一块空间切给父类。但是如果父类对象赋值给子类对象,那就会导致内存越界访问的问题。
dynamic_cast,便是当父类赋值给子类的时候,会另外开辟一个空间,然后用父类的元素去构造一个新的子类对象,再进行赋值。