四种类型转换

默认分类 · 2024-05-14 · 55 人浏览

C++引入了四种更加安全的强制类型转换运算符,分别是const_caststatic_castreinterpret_castdynamic_cast,作用和区别如下:

  1. const_cast:

    去除const(volatile)属性, 只针对指针、引用和this指针有效,其他情况会报错

    示例

    int main() {
    const int a = 0;
    // int *p = &a; // 这样会报错
    int *p = const_cast<int*>(&a); // 去除了 const 属性
    // int c = const_cast<int>(a); // 报错,因为只针对指针、引用和this指针有效 
    return 0;
    }
  2. static_cast:

    用于各种隐式转换例如

    • void* 转换为任意类型的指针
    • 任意类型的指针转换为void*
    • 编译器允许的跨类型转换,比如char类型转换为int类型,doubleint

    static_cast 不做类型检查, 允许子类类型的指针安全转换为父类类型的指针,相反也能转换能成功但是不安全,结果未知,只能在拥有继承关系的类之间进行转换

    示例

    class Base {
    };
    
    class Derived : public Base { 
    };
    
    int main() {
        Derived* d = new Derived();
        Base* b = static_cast<Base*>(d); // 子类转换为父类, 是安全的
        Base* b1 =  new Base();
        Derived* d1 = static_cast<Derived*>(b1); // 父类转换为子类,不安全
        return 0;
    }
  3. dynamic_cast:

    动态类型转换,只能用于含有虚函数的类, 不然会报错, dynamic_cast 会做类型检查, 检测在运行时进行。如果是非法的,对于指针返回NULL,对于引用抛bad_cast异常。将子类类型的指针转换为父类类型的指针与 static_cast 是一样的

    示例

    class Base { virtual void dummy() {} // 如果没有虚函数dynamic_cast会编译报错};
    class Derived : public Base {};
    
    
    
    int main() {
        //指针
        Base* b1 = new Derived;
        Base* b2 = new Base;
        Derived* d1 = dynamic_cast<Derived *>(b1); // 成功
        Derived* d2 = dynamic_cast<Derived *>(b2); // 失败返回空指针
        //引用
        Base& b3 = *b1;
        Base& b4 = *b2;
        try {
            Derived& d3 = dynamic_cast<Derived&>(b3); // 成功
            Derived& d4 = dynamic_cast<Derived&>(b4); // 失败抛出异常
        } catch (bad_cast& e) {
            cout << e.what() << endl;
        }
    }
  4. reinterpret_cast

    就像传统的强制类型转换一样对待所有指针的类型转换。几乎什么都可以转,比如将int转指针,可能会出问题, 它不进行检查,只是进行强制的复制

    示例

    int main() {
        int a = 10;
        int* p = &a;
        int* c = reinterpret_cast<int*>(a); // 可以把整数转成指针
        char* p1 = reinterpret_cast<char*>(p); // 可以把指针转成另一种指针
    }   

相比于 c 的强制类型转换的优点

  • 语义更加明确,类型转换更容易在代码里被发现。
  • C++编译器在编译阶段就会针对错误的转换报错,而C风格不会
  • C 的强制转换表面上看起来功能强大什么都能转,但是转化语义不够明确,不能进行错误检查,容易出错。
c++
Theme Jasmine by Kent Liao