强制类型转换
一、C风格的强制类型转换 在C语言中,强制类型转换是通过“(目标类型)变量名”或者“目标类型(变量名)所实现的”,例如(int)3.14或者int(3.14),前者的方式常称之为C风格的类型转换,后者则被称之为函数风格的强制类型转换
二、static_cast
static_cast<目标类型>(expression)
static即为静态类型转换,在编译时进行类型检查以及类型转换,但没有运行时类型检查来保障安全性,其作用主要有4个
1.相关类型间的转换,double->int,int->double,float->int 等等
double pi = 3.14;
int k = static_cast<int>(pi);
2.子类对象向父类对象的转换,子类对象向父类对象相当于对子类对象进行了一个“切片”,只会保留父类中存在的信息
Base b = static_cast<Base>(derived_ins);
注意:把子类的指针或引用转换成基类表示是安全的,进行的是上行转换是安全的,把父类转换成字类时,进行下行转换,由于没有动态类型检查,所以是不安全的 3.void * 与其他类型指针的转换, operator new 就是使用static_cast将void *转换成指向具体对象的指针
void *memory = operator new(sizeof(Buz());
buz = static_cast<Buz *>(memory);
4.左值和右值之间的转换,move()方法将一个左值转换成右值,其内部就是使用static_cast实现的
三丶dynamic_cast
dynamic_cast<目标类型>(expression)
dynamic_cast主要用于父类和字类之间的类型转换,能够将父类指针或者引用安全的转换成子类的指针或者引用,这个过程发生在运行时,并且dynamic_cast正确工作的前提时父类中至少存在一个虚函数也就是说,dynamic_cast主要用在多态类类型,有时候我们需要将基类指针特例化,就可以使用类模板进行类型转换
当转换目标是指针时,也就是子类指针,如果转换失败,则返回空指针,当我们转换目标是引用时,也就是子类引用,若转换失败,则会抛出bad_cas异常,因为没有空引用
四、const_cast
const_cast<目标类型>(expression)
const_cast的主要作用就是添加或去除指针或者引用的const属性,但不可以是值类型,该类型转换绝大部分出现在函数重载中,其余场合使用const_cast去除const属性是一个很危险的行为
int a = 1;
const int* ptr = &a;
int* ktr = const_cast<int *>(ptr);
*ktr = 2;
cout<<*ktr<<endl;
这段代码能够正常编译和运行,但是强烈建议不要这么做,很容易引发系统漏洞
用途:函数重载 比如有一个这样的函数,接收两个string,返回长度较长的那个
string& longer_string(string& a, string& b) {
return a.size() > b.size() ? a : b;
}
这个函数有个局限性,不能接受const实参,不能接收右值,改良后如下
const string& longer_string(const string& a, const string& b) {
return a.size() > b.size() ? a : b;
}
这样就没问题了,const和非const字符串都能使用 但是上面改良的版本也有问题,因为不管实参是否带有const属性的,我们的longer_string都将其隐式的转换成了常量引用了
string& longer_string(string& a, string& b) {
auto& r = longer_string(const_cast<const string&>(a), const_cast<const string&>(b));
return const_cast<string&>(r);
}
这样一来,我们就不再需要在longer_string的非常量引用的重载函数中重复书写逻辑,而只是进行一些类型转换,最后一个版本我们首先利用const_cast为形参添加const属性,得到的结果再去除const属性,行为安全。因此,对于一个非常量的指针或者引用来说,我们可以先将其转换成const指针或者引用,然后做一些事情,事情一做完,再把它们的const属性摘掉,大家就当无事发生过。 const_cast只对底层const有用,对于顶层const没用
五丶reinterpret_cast
reinterpret<目标类型>(expression)
reinterpret_cast主要用于处理无关类型间的转换,也就是说两个转换类型之间没有任何关系,怎么转都行
常见用途:将一种类型指针转换成另一种类型的指针,按照转换后的内存重新解释内存中的内容
int i = 68;
int* ptr = &i;
char* ktr = reinterpret_cast<char*>(ptr);
cout << *ktr << endl;
这里我们将int指针转换成了char类型的指针,也就是说原本ptr指针读取4字节的内容,而ktr能只会读取变量i的第一个字节
|