static_cast、dynamic_cast、const_cast与reinterpret_cast

强制类型转换

区别于隐式的类型转换如:

//数组转指针类型
int ia[10];
int* ip = ia;
//指针转bool类型
char *cp = get_string();
if(cp)
//类类型定义的转换
string s, t="a value";

有时我们需要显示地将对象强制转换成另外一种类型.这种方法称作强制类型转换(cast),形式如下:
cast-name(expression);

一、static_cast

任何具有明确定义的类型转换,只要不包含底层const,都可以使用static_cast

题外话:
那么什么是底层const呢?
底层const表示指针所指对象或是引用对象是一个常量,举一个栗子:

int i = 0;
int *const p1 = &i;		//顶层const
const int ci = 25;		//顶层const,不能改变ci的值
const int* p2 = &ci;		//底层const,指针p2的值是可以改变的,ci的值是不可改变的
const int* const p3 = p2; //右边的const是顶层const,左边的const是底层的底层const
const int &m = ci;		//引用的const都是底层const

换句话说,只要expression指向的内存是能被修改的,就可以使用static_cast
用法:
(1)用于基本数据类型之间的转换,如把int转换为char,把int转换成enum,但这种转换的安全性需要开发者自己保证(这可以理解为保证数据的精度,即程序员能不能保证自己想要的程序安全),如在把int转换为char时,如果char没有足够的比特位来存放int的值(int>127或int<-127时),那么static_cast所做的只是简单的截断,及简单地把int的低8位复制到char的8位中,并直接抛弃高位。

(2)把void*(这个不叫空指针)转换成目标类型指针,如:

void* p4 = &i;
int* ip = static_cast<int*>(p4);

(3)把任何类型的表达式类型转换成void类型

(4)用于类层次结构中父类和子类之间指针或引用的转换。

对于以上第(4)点,存在两种形式的转换,即上行转换(子类到父类)和下行转换(父类到子类)。对于static_cast,上行转换时安全的,而下行转换时不安全的,为什么呢?因为static_cast的转换时粗暴的,它仅根据类型转换语句中提供的信息(尖括号中的类型)来进行转换,这种转换方式对于上行转换,由于子类总是包含父类的所有数据成员和函数成员,因此从子类转换到父类的指针对象可以没有任何顾虑的访问其(指父类)的成员。而对于下行转换为什么不安全,具体原理在dynamic_cast中说明。

二、dynamic_cast

static_cast具有编译期类型检查
dynamic_cast具有运行时类型检查,因此可以保证下行转换的安全性,何为安全性?即转换成功就返回转换后的正确类型指针,如果转换失败,则返回0(如果是引用就抛出bad_cast异常),之所以说static_cast在下行转换时不安全,是因为即使转换失败,它也不返回。

dynamic_cast适用于以下情况:
1.上行转换(安全)
2.下行转换:当我们想使用基类对象的指针或引用执行某个派生类操作并且该操作不是虚函数.一般来说我们可以使用虚函数完成运行时多态.但是当我们没有使用虚函数的时候,我们则可以使用dynamic_cast完成这一操作,但是这种操作是存在着潜在的风险的,所以程序员必须知道dynamic_cast进行强转会不会成功.(最好使用虚函数)

dynamic_cast用法与static_cast不一样
指针类型转换:

    Base* p = new Child();
    if(Child* pb = static_cast<Child*>(p))
    {   
       
    } else {
        cout << "error" <<endl;
    } 

引用类型转换:

void f(const Base& b)
{
	try{
		const Child &d = dynamic_cast<const Child&>(b);
	} catch (bad_cast) {
		//TODO
	}
}

!!!dynamic_cast会比较虚函数表,也就是一层一层匹配v-table,开销巨大
故,如果继承深度不深的话,可以考虑
如果是多继承,建议使用

三、const_cast

const_cast只能改变运算对象的底层const
换言之,const_cast可以将一个只读对象变成“可读写”对象,但是如果对象是常量就会产生未定义的结果

使用方式:

const char* pc;
char* p = const_cast<char*>(pc);
const int i = 1;
int s = const_cast<int>(i);	//这是错误的

四、reinterpret_cast(强烈建议不使用)

举个栗子:

int *ip;
char* pc = reinterpret_cast<char*>(ip);
char* ps = static_cast<char*>(ip);	//错误

五、旧式强制类型转换(不建议使用)

type(expr);
(type) expr;
举个栗子:
int a = 2;
char c = (char)a;

参考文章:
https://blog.csdn.net/qq_26849233/article/details/62218385
https://blog.csdn.net/debugconsole/article/details/9379627 (不是原文)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值