C++语言基础(24)-四种类型转换运算符(static_cast、dynamic_cast、const_cast和reinterpret_cast)...

本文详细介绍了C++中的四种类型转换:static_cast、const_cast、reinterpret_cast和dynamic_cast的使用方法及注意事项。从基本语法到实际应用案例,帮助读者深入理解不同类型转换的特点及其潜在风险。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

一.static_cast

static_cast 只能用于良性转换,这样的转换风险较低,一般不会发生什么意外,如:

#include <iostream>
#include <cstdlib>
using namespace std;

class Complex{
public:
    Complex(double real = 0.0, double imag = 0.0): m_real(real), m_imag(imag){ }
public:
    operator double() const { return m_real; }  //类型转换函数
private:
    double m_real;
    double m_imag;
};

int main(){
    //下面是正确的用法
    int m = 100;
    Complex c(12.5, 23.8);
    long n = static_cast<long>(m);  //宽转换,没有信息丢失
    char ch = static_cast<char>(m);  //窄转换,可能会丢失信息
    int *p1 = static_cast<int*>( malloc(10 * sizeof(int)) );  //将void指针转换为具体类型指针
    void *p2 = static_cast<void*>(p1);  //将具体类型指针,转换为void指针
    double real= static_cast<double>(c);  //调用类型转换函数
   
    //下面的用法是错误的
    float *p3 = static_cast<float*>(p1);  //不能在两个具体类型的指针之间进行转换
    p3 = static_cast<float*>(0X2DF9);  //不能将整数转换为指针类型

    return 0;
}

二.const_cast

const_cast用来去掉表达式的 const 修饰或 volatile 修饰。换句话说,const_cast 就是用来将 const/volatile 类型转换为非 const/volatile 类型。如:

#include <iostream>
using namespace std;

int main(){
    const int n = 100;
    int *p = const_cast<int*>(&n);
    *p = 234;
    cout<<"n = "<<n<<endl;
    cout<<"*p = "<<*p<<endl;

    return 0;
}

运行结果:

n = 100
*p = 234

&n用来获取 n 的地址,它的类型为const int *,必须使用 const_cast 转换为int *类型后才能赋值给 p。由于 p 指向了 n,并且 n 占用的是栈内存,有写入权限,所以可以通过 p 修改 n 的值。

至于为什么通过 n 和 *p 输出的值不一样呢?这是因为 C++ 对常量的处理更像是编译时期的#define,是一个值替换的过程,代码中所有使用 n 的地方在编译期间就被替换成了 100。换句话说,第 8 行代码被修改成了下面的形式:

cout<<"n = "<<100<<endl;

这样以来,即使程序在运行期间修改 n 的值,也不会影响 cout 语句了。

三.reinterpret_cast 

reinterpret_cast 这种转换仅仅是对二进制位的重新解释,不会借助已有的转换规则对数据进行调整,非常简单粗暴,所以风险很高

#include <iostream>
using namespace std;

class A{
public:
    A(int a = 0, int b = 0): m_a(a), m_b(b){}
private:
    int m_a;
    int m_b;
};

int main(){
    //将 char* 转换为 float*
    char str[]="http://c.biancheng.net";
    float *p1 = reinterpret_cast<float*>(str);
    cout<<*p1<<endl;
    //将 int 转换为 int*
    int *p = reinterpret_cast<int*>(100);
    //将 A* 转换为 int*
    p = reinterpret_cast<int*>(new A(25, 96));
    cout<<*p<<endl;
   
    return 0;
}

运行结果:

3.0262e+29
25

个人感觉这个关键字很危险,所以不推荐使用.

四.dynamic_cast

dynamic_cast 用于在类的继承层次之间进行类型转换,它既允许向上转型(Upcasting),也允许向下转型(Downcasting)。向上转型是无条件的,不会进行任何检测,所以都能成功;向下转型的前提必须是安全的,要借助 RTTI 进行检测,所有只有一部分能成功。

有以下两点需要注意:

1).newType 和 expression 必须同时是指针类型或者引用类型。换句话说,dynamic_cast 只能转换指针类型和引用类型,其它类型(int、double、数组、类、结构体等)都不行。

2).对于指针,如果转换失败将返回 NULL;对于引用,如果转换失败将抛出std::bad_cast异常。

例:

#include <iostream>
using namespace std;

class A{
public:
    virtual void func() const { cout<<"Class A"<<endl; }
private:
    int m_a;
};

class B: public A{
public:
    virtual void func() const { cout<<"Class B"<<endl; }
private:
    int m_b;
};

class C: public B{
public:
    virtual void func() const { cout<<"Class C"<<endl; }
private:
    int m_c;
};

class D: public C{
public:
    virtual void func() const { cout<<"Class D"<<endl; }
private:
    int m_d;
};

int main(){
    A *pa = new A();
    B *pb;
    C *pc;
   
    //情况①
    pb = dynamic_cast<B*>(pa);  //向下转型失败
    if(pb == NULL){
        cout<<"Downcasting failed: A* to B*"<<endl;
    }else{
        cout<<"Downcasting successfully: A* to B*"<<endl;
        pb -> func();
    }
    pc = dynamic_cast<C*>(pa);  //向下转型失败
    if(pc == NULL){
        cout<<"Downcasting failed: A* to C*"<<endl;
    }else{
        cout<<"Downcasting successfully: A* to C*"<<endl;
        pc -> func();
    }
   
    cout<<"-------------------------"<<endl;
   
    //情况②
    pa = new D();  //向上转型都是允许的
    pb = dynamic_cast<B*>(pa);  //向下转型成功
    if(pb == NULL){
        cout<<"Downcasting failed: A* to B*"<<endl;
    }else{
        cout<<"Downcasting successfully: A* to B*"<<endl;
        pb -> func();
    }
    pc = dynamic_cast<C*>(pa);  //向下转型成功
    if(pc == NULL){
        cout<<"Downcasting failed: A* to C*"<<endl;
    }else{
        cout<<"Downcasting successfully: A* to C*"<<endl;
        pc -> func();
    }
   
    return 0;
}

运行结果:

Downcasting failed: A* to B*
Downcasting failed: A* to C*
-------------------------
Downcasting successfully: A* to B*
Class D
Downcasting successfully: A* to C*
Class D

 

C++中有四种强制类型转换,分别是reinterpret_castconst_caststatic_castdynamic_castreinterpret_cast用于进行底层的重新解释转换,可以将一个指针或引用转换为其他类型的指针或引用,甚至可以将指针转换为整数类型。但是使用reinterpret_cast需要非常小心,因为它是一种非常危险的操作,可能会导致未定义的行为。 const_cast用于移除const属性,可以将const修饰的变量或指针转换为非const类型。这可以用于去除const限定符,从而修改被const修饰的变量的值。 static_cast用于进行常见的类型转换,可以将一个表达式转换为另一种类型,例如基本数据类型之间的转换、父类指针或引用转换为子类指针或引用、以及void指针任意类型的指针之间的转换。但是需要注意,在进行父类到子类的转换时,只有当父类指针或引用实际上指向了一个子类对象时,才能进行成功的转换。 dynamic_cast用于在继承关系中进行安全的向下转型(downcasting)。它可以将一个父类指针或引用转换为子类指针或引用,同时会进行类型检查,确保转换是安全的。如果转换失败,dynamic_cast会返回一个空指针或抛出一个std::bad_cast异常。 这四种强制类型转换在不同的场景下有不同的应用,可以根据具体的需求选择合适的转换方式。但是需要注意,在使用这些强制类型转换时,一定要谨慎慎重,确保转换的安全性正确性。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [C++中的类型转换static_castdynamic_castconst_castreinterpret_cast总结](https://download.csdn.net/download/weixin_38629976/12808232)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [C++四种类型转换reinterpret_cast/const_cast/static_cast /dynamic_cast](https://blog.csdn.net/salmonwilliam/article/details/113941785)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [C++四种cast转换(const_caststatic_castdynamic_cast、reinpreter_cast类型转换运算符](https://blog.csdn.net/Dontla/article/details/130792118)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值