[C++](27)强制类型转换 static_cast reinterpret_cast const_cast dynamic_cast

引入

C语言的类型转换

在C语言中,如果赋值运算符左右两侧的类型,形参与实参的类型,函数返回值的类型与接收值的类型不同,就需要发生类型转换。C语言存在两种类型转换:隐式类型转换显式类型转换

  1. 隐式类型转换:编译器在编译阶段自动进行,能转则转,不能转则编译失败。
  2. 显式类型转换:程序员自己处理。

缺陷:

  1. 转换的可视性较差, 所有的转换形式都是以一种相同形式书写,难以跟踪错误的转换。
  2. 隐式类型转换在某些情况下会出问题,比如数据精度的丢失
  3. 显式类型转换将所有情况都混合在一起,代码不够清晰。

C++强制类型转换

C++ 为了增强类型转换的可视性,引入了 4 种强制类型转换的操作符

  • static_cast
  • reinterpret_cast
  • const_cast
  • dynamic_cast

C++ 兼容C语言的强制类型转换,但还是希望大家使用新的强制类型转换操作符,以此来提高规范性,可读性,降低出错率。

static_cast

static_cast 用于非多态类型的转换(静态转换),编译器隐式执行的任何类型都可以用 static_cast ,但它不能用于两个不相关的类型之间的转换。

double d = 10.24;
int a = static_cast<int>(d);
cout << a << endl;	//10

reinterpret_cast

reinterpret_cast 可以用于两个不相近的类型之间的转换

比如用指针转int类型,只能用 reinterpret_cast ,用 static_cast 会报错。

int* p = &a;
//int x = static_cast<int>(p); // 报错:E0171	类型转换无效
int x = reinterpret_cast<int>(p);
cout << x << endl;

const_cast

用于去除变量的 const 属性,方便赋值

如以下情景,不能使用reinterpret_cast

const int ca = 2;
//int* pi = reinterpret_cast<int*>(&ca); //报错 E0694	reinterpret_cast 无法丢掉常量或其他类型限定符
int* pi = const_cast<int*>(&ca);
*pi = 3;
cout << ca << endl;
cout << *pi << endl;

这里就有个小问题了,结果是什么?

  • 答案:2 3,这里涉及编译器的优化,被 const 修饰的 ca 编译器不认为它会被修改了,所以访问的时候直接到缓存或者寄存器去取,用 *pi 修改了内存中的值影响不到缓存或寄存器,所以最后打印的 ca 还是 2。

如果你希望编译器去内存中取 const 变量,可以在前面加 volatile,此时的结果就是 3 3 了。

volatile const int ca = 2;
  • 因为该关键字会去掉 const 属性,所以比较不安全,如果你不确定要去掉 const 属性,那就用 reinterpret_cast

dynamic_cast

规范向下转换,转换是安全的

  • 向上转换:子类对象指针/引用转换成父类指针/引用
  • 向下转换:父类对象指针/引用转换成子类指针/引用

对象是天然支持向上转换的(切片),但是不支持向下转换。

注意:

  1. dynamic_cast 只能用于父类含有虚函数的类
  2. dynamic_cast 会先检查是否能转换成功,能成功则转换,不能则返回 0

利用它我们可以检查一个父类指针是指向子类对象还是父类对象:

  • 指向父类对象的父类指针转换成子类指针,会出现越界,所以转换失败。
  • 指向子类对象的父类指针转换成子类指针,没有问题,转换成功。
class A
{
public:
    virtual void f() {} // 父类必须有虚函数才能用dynamic_cast
};

class B : public A
{};

void fun(A* pa)
{
    if (dynamic_cast<B*>(pa))
    {
        cout << "转换成功" << endl;
    }
    else
    {
        cout << "转换失败" << pa << endl;
    }
}

void test2()
{
    A a;
    B b;
    fun(&a);
    fun(&b);
}
//转换失败0093FC38
//转换成功
  • 所以我们说它是安全的,因为它能检测到你的指针能不能转换,不能转换就不转。
  • 在多态类型(父类有虚函数)的情况下进行向下转换,推荐使用 dynamic_cast ,更加安全。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

世真

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值