Published on

C++ 中的 Cast 操作总结

C++ 提供了多种类型转换操作,主要分为以下几种:

  1. static_cast:

    • 用于执行编译时类型转换,例如基本类型之间的转换、void 指针转换等。
    • 可以用于类层次结构中基类和派生类之间指针或引用的转换(向上转换总是安全的,向下转换需要程序员保证类型安全)。
    • 不提供运行时的类型检查。
    • 示例:
    double d = 3.14;
    int i = static_cast<int>(d); // double -> int
    
    class Base {};
    class Derived : public Base {};
    Derived* derived = new Derived();
    Base* base = static_cast<Base*>(derived); // Derived* -> Base* (Upcast)
    
  2. dynamic_cast:

    • 主要用于类层次结构中基类和派生类之间指针或引用的安全向下转换。
    • 在运行时进行类型检查,如果转换不安全(即,指针或引用实际指向的对象不是目标类型),则:
      • 对于指针,返回 nullptr
      • 对于引用,抛出 std::bad_cast 异常。
    • 要求基类至少包含一个虚函数(通常是虚析构函数),以便启用运行时类型信息 (RTTI)。
    • 示例:
    class Base { virtual void foo() {} };
    class Derived : public Base {};
    Base* base = new Derived();
    Derived* derived = dynamic_cast<Derived*>(base); // Base* -> Derived* (Downcast)
    if (derived) {
        // 转换成功
    } else {
        // 转换失败,base 实际不是 Derived*
    }
    
  3. const_cast:

    • 用于添加或移除变量的 constvolatile 属性。
    • 只能修改对象的常量性,不能改变对象的类型。
    • 如果对象本身是 const 的,即使使用 const_cast 移除了常量性,通过该指针或引用修改对象仍然是未定义行为。
    • 示例:
    const int i = 10;
    int* ptr = const_cast<int*>(&i);
    *ptr = 20; // Undefined behavior!
    
    class MyClass {};
    const MyClass obj;
    MyClass* ptr2 = const_cast<MyClass*>(&obj); // 合法,但修改 obj 的成员可能是未定义行为
    
  4. reinterpret_cast:

    • 最强大的类型转换操作符,允许将任何指针类型转换为任何其他指针类型,以及将指针转换为整数类型,反之亦然。
    • 不对类型进行任何检查,仅仅是重新解释内存中的位模式。
    • 非常危险,容易出错,应该谨慎使用。
    • 通常用于底层编程,例如处理硬件接口或进行二进制数据操作。
    • 示例:
    int i = 10;
    int* ptr = &i;
    void* vptr = reinterpret_cast<void*>(ptr); // int* -> void*
    uintptr_t addr = reinterpret_cast<uintptr_t>(ptr); // int* -> uintptr_t
    
  5. bit_cast (C++20):

    • 用于在具有相同大小的对象之间进行转换,直接复制对象的位模式。
    • 不改变位模式,只是改变类型。
    • 如果源类型和目标类型的大小不同,则会导致编译错误。
    • 示例:
    #include <bit>
    float f = 3.14f;
    uint32_t i = std::bit_cast<uint32_t>(f); // float -> uint32_t
    
  6. duration_cast (C++11):

    • 用于在不同的 std::chrono::duration 类型之间进行转换。
    • 例如,将毫秒转换为秒。
    • 示例:
    #include <chrono>
    using namespace std::chrono;
    
    auto milliseconds = 1500ms;
    auto seconds = duration_cast<seconds>(milliseconds); // milliseconds -> seconds
    
  7. C 风格的类型转换:

    • (type) expressiontype(expression)
    • 可以执行任何类型转换,包括 static_castconst_castreinterpret_cast 的组合。
    • 不安全,不推荐使用,应该尽量使用 C++ 提供的四种类型转换操作符。
    • 示例:
    double d = 3.14;
    int i = (int)d;
    

THE END