《More Effective C++》

第一章 基础议题

2.最好使用C++转型操作符

1.static_cast
static_cast基本上拥有与C旧式转换相同的威力与意义,以及相同的限制,它是与C-style最接近的一个转换;
使用情况概述:通常是数值数据类型转换(比如float->int);不执行运行时类型检查(安全性不如dynamic_cast);能用于多态向上转换,向下则不一定能保证真确;
补充:任何编写程序时能够明确的类型转换都可以使用static_cast(static_cast不能转换掉底层const,volatile和__unaligned属性)。由于不提供运行时的检查,所以叫static_cast,因此,需要在编写程序时确认转换的安全性。

2.const_cast
const_cast用于改变表达式中的常量性(const)或易变性(volatile),以及__unaligned属性。
使用情况概述:最常用的是将const转换为非const;当然它其实还能去掉volatile性质、改变__unaligned的心性质;
疑问:旧式的C转换如何做到const_cast同样效果呢?

3.dynamic_cast
dynamic_cast用于多态的安全向下转型以及向上转型。
使用情况概述:用于多态类型向上/向下转型;会执行运行时检查;

4.reinterpret_cast
reinterpret_cast就是bit的简单重新解释,几乎什么都可以转。
使用情况概述:尽量少使用

注:static_cast与const_cast的区别
在多重继承上可以体现二者的区别:

class A {
    public:
    int m_a;
};
 
class B {
    public:
    int m_b;
};
 
class C : public A, public B {};

int main(){
	C c;
	printf("%p, %p, %p", &c, reinterpret_cast<B*>(&c), static_cast <B*>(&c));
}

//打印结果: 0x7fff17de3820, 0x7fff17de3820, 0x7fff17de3824

C++通过指针来访问成员的过程,实际上是根据指针的类型,找到改类定义,并从中找到要访问的成员的地址偏移,然后从对象指针开始加上偏移,便得到了成员的地址,然后进行访问操作。所以类定义的作用之一在于,确定成员的内存偏移。

static_cast会在编译期将指针在类的内存空间内移动,并最终指向到你转换到的内存上。在上面的例子中,当将C的指针转型为B型指针时,实际上将指针的数值修改了,指向了内存中B类的开头位置。当使用转换后的指针访问B的成员时,先到B类定义查到B的内存分布,然后进行指针便宜,访问。一切都是正确的。

reinterpret_cast并不会在转型是修改指针的值,而是告诉编译器,这个指针是某个类型的指针,仅此而已。所以当使用此转型方式转换C的指针到B类型时,指针仍然指向原来的位置,即C的开头,也是A的开头。这时如果访问B*的成员m_b,那么先到B上查到m_b的地址偏移为一个整型的字节大小(一般是4),那么你实际是将指针偏移到了A类的m_a成员处,访问的是m_a的内容。这种错误是编译器不明白的,你的程序即将崩溃。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值