命名强制类型转换

命名强制类型转换

1. static_cast

static_cast 主要用于编译时的类型转换,它通常用于类层次结构中的相关类型、基本数据类型之间的转换以及一些隐式类型转换的显式表示。

任何具有明确的类型转换,只要不包含底层const,都可以使用static_cast。一般,如果编译器发现一个较大的算术类型企图赋值给较小的类型,就会给出警告信息,但使用static_cast,警告信息就会被关闭。

double doubleValue = 3.14;
int intValue = static_cast<int>(doubleValue);

static cast对于编译器无法自动执行的类型转换也非常有用。例如,我们可以使用static cast 找回存在于 void*指针中的值:

void*p= &d;//正确:任何非常量对象的地址都能存入void
//正确:将void*转换回初始的指针类型
double *dp=static_cast<double*>(p);

当我们把指针存放在 void*中,并且使用static cast将其强制转换回原来的类型时,应该确保指针的值保持不变。也就是说,强制转换的结果将与原始的地址值相等,因此我们必须确保转换后所得的类型就是指针所指的类型。类型一旦不符,将产生未定义的后果。

2. dynamic_cast

dynamic_cast 用于在运行时进行安全的类型转换,特别用于处理多态类层次结构。它要求类中至少有一个虚函数,并且允许在派生类指针或引用和基类之间进行安全的向上或向下转型。

dynamic cast运算符(dynamic cast operator)的使用形式如下所示:

  • dynamic_cast<type*>(e)
  • dynamic_cast<type&>(e)
  • dynamic_cast<type&&>(e)

其中,type必须是一个类类型,并且通常情况下该类型应该含有虚函数。在第一种形式中e必须是一个有效的指针;在第二种形式中,e必须是一个左值;在第三种形式中,e不能是左值。

在上面的所有形式中,e的类型必须符合以下三个条件中的任意一个:e的类型是目标e的公有派生类、e的类型是目标tpe的公有基类或者e的类型就是目标bpe的类型。如果符合,则类型转换可以成功。否则,转换失败。如果一条dynamic cast语句的转换目标是指针类型并且失败了,则结果为0。如果转换目标是引用类型并且失败了,则 dynamic_cast 运算符将抛出一个bad_cast异常(因为不存在所谓的空引用)。

if(Derived *dp=dynamic_cast<Derived*>(bp)){
    //使用dp指向的 Derived 对象
}else{
    //bp 指向一个Base 对象
    //使用bp指向的 Base对象
}
//如果bp指向 Derived对象,则上述的类型转换初始化dp并令其指向bp所指的Derived对象。此时,if语句内部使用Derived操作的代码是安全的。否则,类型转换的结果为0,dp为0意味着if语句的条件失败,此时else 子句执行相应的 Base 操作。

值得注意的一点是,我们在条件部分定义了dp,这样做的好处是可以在一个操作中同时完成类型转换和条件检查两项任务。而且,指针dpif语外部是不可访问的。一旦转换失败,即使后续的代码忘了做相应判断,也不会接触到这个未绑定的指针,从而确保程序是安全的。

void f(const Base &b){
	try {
		const Derived &d=dynamic_cast<const Derived&>(b);
        //使用b引用的Derived对象
    }catch(bad_cast){
        //处理类型转换失败的情况
    }

dynamic_pointer_cast 智能指针由基类转为派生类指针

#include <iostream>

int main() {
    // 创建一个派生类对象的 shared_ptr
    std::shared_ptr<Base> basePtr = std::make_shared<Derived>();

    // 使用 dynamic_pointer_cast 进行类型转换
    std::shared_ptr<Derived> derivedPtr = std::dynamic_pointer_cast<Derived>(basePtr);

    if (derivedPtr) {
        // 转换成功
        std::cout << "Dynamic cast successful." << std::endl;
    } else {
        // 转换失败
        std::cout << "Dynamic cast failed." << std::endl;
    }

    return 0;
}

3. const_cast

const_cast 主要用于添加或移除 const 限定符。它用于在需要时进行常量性转换,但在进行此类转换时应谨慎,因为可能导致未定义的行为。

只有const_cast能改变表达式的常量属性,使用其他形式的命名强制类型转换改变表达式的常量属性都将引发编译器错误。同样的,也不能用const_cast改变表达式的类型:

const int* constIntPtr = new const int(42);
int* intPtr = const_cast<int*>(constIntPtr);

4. reinterpret_cast

reinterpret_cast通常为运算对象的位模式提供较低层次上的重新解释,用于进行底层的、不安全的类型转换,通常用于指针或引用之间的转换,以及整数和指针之间的转换。这种转换是非常低级的,可能会导致未定义的行为,因此在使用时需要非常小心。

int intValue = 42;
double* doublePtr = reinterpret_cast<double*>(&intValue);

注意事项:

  • 尽量避免使用 reinterpret_cast,因为它进行了非常低级别的转换,容易引起错误。
  • 使用 dynamic_cast 时,确保类层次结构中至少有一个虚函数,并且尽量遵循面向对象设计原则。
  • 在使用类型转换时,要谨慎确保转换的安全性,以避免运行时错误。
  • 13
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值