前言
在C语言中,我们,就知道强制类型转换和隐式类型的转换,但是这种转换其实是不太安全的,既然我们学了C++,那么我们就应该尽量使用c++的类型转换,为什么呢?
因为 c++ 中类型转换的方式,他们都是通过类模板的方式实现,安全性得到保证,通过不同的用途使用不同的显示类型转换模板
C语言的强制类型转换
C风格的强制转换(Type Cast)容易理解,不管什么类型的转换都可以使用使用下面的方式.
TypeName b = (TypeName)a;
c++版本 四种强制转换类型函数
const_cast
主要作用是移除变量的const限定符从而改变表达式的常量属性。不能改变其他属性,如把一个变量int变为double,这是未定义的行为。
const_cast(expression); //type,转换的目的类型
这里我们需要注意,const_cast只能改变运算对象的底层const,换句话来说,就是服务于指针和引用。
•常量指针转化为非常量的指针,并且仍然指向原来的对象
•常量引用转化为非常量的引用,并且仍然指向原来的对象
补充:如果对象本身不是一个常量,使用强制类型转换获得写权限是合法的行为;然而如果是对象是一个常量,再使用const_cast执行写操作就会产生未定义的后果,不执行写操作就没事!
char p[123]="123";
const char* s = p;
char* h = const_cast<char*>(s);
h[3] = '4';
const char* s = "1235";
char* h = const_cast<char*>(s);
h[3] = '4'; //发生错误
const_cast经常用在函数重载上,主要就是用来去掉变量的const属性
static_cast(静态转换)
1、static_cast 作用和C语言风格强制转换的效果基本一样,由于没有运行时类型检查来保证转换的安全性,所以这类型的强制转换和C语言风格的强制转换都有安全隐患。 也就是说,当需要把一个较大的算术类型赋值给较小的类型时,就可以用上static_cast, 这里的精度损失是程序员事先已经明确的
2、用于类层次结构中基类(父类)和派生类(子类)之间指针或引用的转换。注意:进行上行转换(把派生类的指针或引用转换成基类表示)是安全的;进行下行转换(把基类指针或引用转换成派生类表示)时,由于没有动态类型检查,所以是不安全的。
补充:当然也可以转换父类子类对象,但是这时候会发生切割现象,并且上行转换时不安全的,如果父类对象转子类对象,子类中还必须有个构造函数且参数是父类的类型,才能编译成功
3、用于基本数据类型之间的转换,如把int转换成char,把int转换成enum。这种转换的安全性需要开发者来维护。
4、static_cast不能转换掉原有类型的const、volatile、或者 __unaligned属性。(前两种可以使用const_cast 来去除)
5、在c++ primer 中说道:c++ 的任何的隐式转换都是使用 static_cast 来实现。
注:static_cast对于编译器无法自动执行的类型转换也非常有用。例如,我们可以使用static_cast找回存在于void*指针中的值:
#include <iostream>
#include <fstream>
using namespace std;
void change( int pt, int n);
int main()
{
double p = 15;
void *y = &p; //任何非常量对象的地址都可以存入void*
double *t = static_cast<double*>(y); //将void*转换回初始的指针类型
//这里值得注意一下,只能强制转回原来的double类型指针,类型一旦不符合,将产生未定义的后果或者出现不符的值
cout<<(*t)<<endl;
return 0;
}
针对上述补充的的第二点(代码演示):
class father{
public:
void func(){
std::cout<<"Father"<<std::endl;
}
};
class son:public father{
public:
son(father& fa){}
son(){}
void func(){
std::cout<<"son"<<std::endl;
}
void add(){
std::cout<<"No"<<std::endl;
}
};
father s;
son fa = static_cast<son>(s);
fa.func();
fa.add();
dynamic_cast (动态转换)
dynamic_cast< type* >(e)
type必须是一个类类型且必须是一个有效的指针
dynamic_cast< type& >(e)
type必须是一个类类型且必须是一个左值
dynamic_cast< type&& >(e)
type必须是一个类类型且必须是一个右值
通常情况下,type应该含有虚函数
注意:e的类型必须符合以下三个条件中的任何一个
1、e的类型是目标类型type的公有派生类
2、e的类型是目标type的共有基类
3、e的类型就是目标type的类型。
如果符合以上三种条件之一,类型转换成功。否则,转换失败。如果dynamic_cast语句的转换目标是指针类型并且失败了,则结果为0。如果转换目标是引用类型并且失败了,将会抛出bad_cast类型异常(意味着我们可以用异常处理)
————————————————————————————————————————————————————
reinterpret_cast (不常用)
reinterpret_cast 主要有三种强制转换用途:
1、改变指针或引用的类型
2、将指针或引用转换为一个足够长度的整形
3、将整型转换为指针或引用类型。
用法为 reinterpret_cast (expression)。
type-id 必须是一个指针、引用、算术类型、函数针或者成员指针。它可以把一个指针转换成一个整数,也可以把一个整数转换成一个指针(先把一个指针转换成一个整数,在把该整数转换成原类型的指针,还可以得到原先的指针值)。
我们映射到的类型仅仅是为了故弄玄虚和其他目的,这是所有映射中最危险的。(这句话是C++编程思想中的原话)。因此, 你需要谨慎使用 reinterpret_cast。