C++中的类型转换
C++中的类型转换:static_cast、reinterpret_cast、const_cast、dynamic_xast
一般情况下我们写的类型转换,就是加上一个圆括号 float a;int b =(int)a;
但是这样有缺陷:因为所有的形式都是一样的。所以可视性就会很差,如果发生错误,不容易找到错误的原因。所以c++引入了强制类型转换操作符。上面的四种。
Static_cast
它用于非多态类型的转换(静态转换),编译器隐式执行的任何类型转换都可以用static_cast,(也就是类型相近的,隐式类型转换),但是它不能用于两个不相关的类型进行转换。
怎么说呢,相近类型,像int 和double float 就是。用于这些普通类型之间的转换
用法:int a = 2;float d = static_cast(a);
一句话总结:这个static_cast就是用来进行类型相近的类型转换的。
Reinterpret_cast
它通常为操作数的位模式提供较低层次的重新解释,用于将一种类型转换为另一种不同的类型。怎么说呢,就是说将一种类型转换为另外一种,那肯定是有风险的了。
举例说明:
typedef int (*FUN)();
int Add(int i,int j)
{
return i + j;
}
void test()
{
FUN f = reinterpret_cast<FUN>(Add);
int b = f(); 这里就是讲一个函数指针转换为了一个整型的数,很可怕吧
cout << b <<endl;
}
总结:也就是说这个reinterpret_cast可以让编译器以FUN的定义方式来看待Add函数。所以说呢很BUG,这个转换指针的代码时不可以移植的,所以呢,是不建议这样是用的。
函数指针并不能保证所有的函数指针都可一这样使用,所以这样用会产生不确定的后果。尽量不要这样用。
一句换总结;reinterpret_cast是用来进行不同类型之间的转换,风险较大,不建议使用
Const_cast
他的用途就是用来删除变量的const属性,方便赋值。
Const int a = 2; int *p = const_cast<int*>(&a); *p = 3;
但是呢,你看呢,本来定义的使const就是不想让他改变,结果你还给我改变了。这样也不太好,所以呢,在用的时候注意,在程序中这个变量的具体意义。
Dynamic_cast
用于将一个父类对象的指针转化为子类对象的指针或者引用。(动态转换,和static_cast相反)
1.向上转型:子类对象指针->父类指针或者引用(不需要转换)
2.向下转型:父类对象指针->子类指针或者引用(用dynamic_cast转型是安全的)
3.Dynamic_cast只能用于含有虚函数的类。
4.Dynamic_cast会先检查是否能转换成功,能就转换,不能就返回0
class AA
{
public:
virtual void f()
{}
};
class BB:public AA
{};
void fun(AA*pa)
{
BB*pb1 = static_cast<BB*>(pa); 强转
BB*pb2 = dynamic_cast<BB*>(pa); 将父类强制转换为子类,会检查是否能转
cout<<"pb1:"<<pb1<<endl;
cout<<"pb2:"<<pb2<<endl;
}
AA a;
BB b;
fun(&a);
fun(&b);
注意:强制类型转换,不管怎么说,它都是强制的,所以说终归是不安全的,所以我们在使用之前都先考虑清楚,是不是必须要用,还有没有其他方法可以代替,如果不需要用,注意要加上强制转换值的作用域,以减少发生错误的机会。尽量避免用强制类型转换
例题
Const int i=0; int j = (int)&i; *j =1;
printf(“%d,%d”,i,j);
输出结果:在C语言中,输出1,1 在c++中输出 0,1;
这是c++中的优化机制,因为 i 是const类型的,编译器就认为我们是不想改变它的,所以就把它放在了寄存器里面,在用的是后就直接从寄存器里面拿出来,这样更加快速,但是呢,在这里我们用指针把它给改变了,看起来输出的时候两个都应该是1 指向同一块空格键了嘛。但是由于c++中编译器的优化,输出的时候直接去寄存器里面找i 所以,结果就还是原来存进去的那个0。(这个题很坑遇到两次了,这次总结类型转换,想起来了,写出来加强一下记忆)。