以下是用代码示例演示C++中四种类型转换(static_castdynamic_castconst_castreinterpret_cast)的用法,每个示例都包含具体场景和注释说明:

#include <iostream>
#include <typeinfo>  // 用于dynamic_cast异常处理
#include <cstdint>   // 用于uintptr_t(存储指针的整数类型)

// 定义用于演示的类层次结构
class Base {
public:
    // 含有虚函数,使Base成为多态类(支持dynamic_cast)
    virtual void print() const {
        std::cout << "This is Base class" << std::endl;
    }
};

class Derived : public Base {
public:
    void print() const override {
        std::cout << "This is Derived class" << std::endl;
    }
    
    // 派生类特有方法
    void derivedMethod() const {
        std::cout << "Calling Derived-specific method" << std::endl;
    }
};

class Unrelated {
public:
    void print() const {
        std::cout << "This is Unrelated class" << std::endl;
    }
};

int main() {
    // 1. static_cast:静态类型转换(编译时检查)
    std::cout << "=== static_cast 示例 ===" << std::endl;
    // 1.1 基本数据类型转换
    int intNum = 10;
    double doubleNum = static_cast<double>(intNum);
    std::cout << "int -> double: " << doubleNum << " (类型大小: " << sizeof(doubleNum) << ")" << std::endl;
    
    // 1.2 派生类到基类的上行转换(安全)
    Derived derivedObj;
    Base* basePtr = static_cast<Base*>(&derivedObj);  // 等价于隐式转换
    basePtr->print();  // 多态调用:输出Derived的print
    
    // 1.3 基类到派生类的下行转换(不安全,无运行时检查)
    Base baseObj;
    Derived* derivedPtr = static_cast<Derived*>(&baseObj);  // 编译通过,但危险
    derivedPtr->print();  // 未定义行为(实际指向Base对象)
    
    // 1.4 void*与其他指针的转换
    int x = 100;
    void* voidPtr = static_cast<void*>(&x);
    int* intPtr = static_cast<int*>(voidPtr);  // 安全转回原类型
    std::cout << "通过void*转换后的值: " << *intPtr << std::endl;
    std::cout << std::endl;


    // 2. dynamic_cast:动态类型转换(运行时检查,仅用于多态类)
    std::cout << "=== dynamic_cast 示例 ===" << std::endl;
    Base* realDerivedPtr = new Derived();  // 实际指向派生类对象
    Base* realBasePtr = new Base();        // 实际指向基类对象
    
    // 2.1 指针转换:成功案例
    Derived* castedDerived = dynamic_cast<Derived*>(realDerivedPtr);
    if (castedDerived != nullptr) {
        std::cout << "dynamic_cast 指针转换成功: ";
        castedDerived->derivedMethod();  // 安全调用派生类方法
    }
    
    // 2.2 指针转换:失败案例
    Derived* failedCast = dynamic_cast<Derived*>(realBasePtr);
    if (failedCast == nullptr) {
        std::cout << "dynamic_cast 指针转换失败(指向基类对象)" << std::endl;
    }
    
    // 2.3 引用转换:成功案例
    Derived& derivedRef = dynamic_cast<Derived&>(*realDerivedPtr);
    std::cout << "dynamic_cast 引用转换成功: ";
    derivedRef.derivedMethod();
    
    // 2.4 引用转换:失败案例(会抛出异常)
    try {
        Derived& badRef = dynamic_cast<Derived&>(*realBasePtr);
    } catch (const std::bad_cast& e) {
        std::cout << "dynamic_cast 引用转换失败: " << e.what() << std::endl;
    }
    
    delete realDerivedPtr;
    delete realBasePtr;
    std::cout << std::endl;


    // 3. const_cast:常量性转换(修改const属性)
    std::cout << "=== const_cast 示例 ===" << std::endl;
    // 3.1 安全场景:原对象本身非const,仅指针是const
    int nonConstVal = 20;
    const int* constPtr = &nonConstVal;
    int* mutablePtr = const_cast<int*>(constPtr);  // 去除const
    *mutablePtr = 30;  // 安全,原对象是非const的
    std::cout << "修改后的值(原对象非const): " << nonConstVal << std::endl;
    
    // 3.2 危险场景:原对象是const,强制修改会导致未定义行为
    const int constVal = 40;
    const int* ptrToConst = &constVal;
    int* badMutablePtr = const_cast<int*>(ptrToConst);
    *badMutablePtr = 50;  // 未定义行为(编译器可能优化constVal为只读)
    std::cout << "原const对象的值(可能未变): " << constVal << std::endl;
    std::cout << "通过指针访问的值(不确定): " << *badMutablePtr << std::endl;
    std::cout << std::endl;


    // 4. reinterpret_cast:重解释转换(底层二进制重解释)
    std::cout << "=== reinterpret_cast 示例 ===" << std::endl;
    // 4.1 指针与整数的转换
    int num = 0x12345678;
    int* numPtr = &num;
    uintptr_t ptrAddr = reinterpret_cast<uintptr_t>(numPtr);  // 指针转整数
    std::cout << "指针地址(整数形式): 0x" << std::hex << ptrAddr << std::dec << std::endl;
    
    int* restoredPtr = reinterpret_cast<int*>(ptrAddr);  // 整数转回指针
    std::cout << "恢复指针后的值: " << *restoredPtr << std::endl;
    
    // 4.2 不同类型指针的转换(危险,语义完全改变)
    float* floatPtr = reinterpret_cast<float*>(numPtr);
    std::cout << "int指针重解释为float指针的值: " << *floatPtr << std::endl;
    // 注意:这里的值与原int值的二进制相同,但语义完全不同(浮点数格式)
    
    // 4.3 无关类指针的转换(危险,无继承关系)
    Unrelated* unrelatedPtr = reinterpret_cast<Unrelated*>(numPtr);
    unrelatedPtr->print();  // 未定义行为(实际指向int变量)

    return 0;
}

代码说明

  1. static_cast 示例

    • 演示了基本类型转换(intdouble)、类层次结构的上下行转换,以及void*与其他指针的转换
    • 注意基类到派生类的下行转换是不安全的,编译器不做运行时检查
  2. dynamic_cast 示例

    • 仅用于多态类(含虚函数),通过运行时类型信息(RTTI)检查转换安全性
    • 指针转换失败返回nullptr,引用转换失败抛出std::bad_cast异常
    • 适合需要安全地将基类指针/引用转换为派生类类型的场景
  3. const_cast 示例

    • 用于修改指针/引用的const属性,仅当原对象本身不是const时修改才安全
    • 若原对象是const,强制修改会导致未定义行为(结果不确定)
  4. reinterpret_cast 示例

    • 直接重解释底层二进制,不进行逻辑转换,结果高度依赖系统架构
    • 演示了指针与整数的转换、不同类型指针的转换,这类转换风险极高,仅用于底层编程

编译运行注意

  • 编译时需启用RTTI(通常默认启用,部分编译器需加-frtti选项)
  • reinterpret_cast的结果可能因编译器和平台(32位/64位)而异,移植性差
  • 实际开发中应优先使用前两种转换,谨慎使用const_cast,尽量避免reinterpret_cast

通过这些示例,可以清晰看到四种转换的适用场景和潜在风险,帮助理解如何在实际代码中正确选择类型转换方式。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐