普通投与静态

这个问题在这里已经有了答案:

  • 什么时候应该使用static_cast,dynamic_cast,const_cast和reinterpret_cast? 6个答案

  • 的static_cast

    static_cast用于基本上想要反转隐式转换的情况,只有一些限制和附加。 static_cast执行运行时检查。 如果你知道你指的是一个特定类型的对象,那么应该使用它,因此检查是不必要的。 例:

    void func(void *data) {
      // Conversion from MyClass* -> void* is implicit
      MyClass *c = static_cast<MyClass*>(data);
      ...
    }
    
    int main() {
      MyClass c;
      start_thread(&func, &c)  // func(&c) will be called
          .join();
    }
    

    在这个例子中,你知道你传递了一个MyClass对象,因此不需要运行时检查来确保这一点。

    的dynamic_cast

    当您不知道对象的动态类型是什么时, dynamic_cast非常有用。 如果引用的对象不包含被转换为基类的类型(当您转换为引用时,在此情况下引发bad_cast异常),它将返回空指针。

    if (JumpStm *j = dynamic_cast<JumpStm*>(&stm)) {
      ...
    } else if (ExprStm *e = dynamic_cast<ExprStm*>(&stm)) {
      ...
    }
    

    如果向下转换(转换为派生类)并且参数类型不是多态,则不能使用dynamic_cast 。 例如,以下代码无效,因为Base不包含任何虚函数:

    struct Base { };
    struct Derived : Base { };
    int main() {
      Derived d; Base *b = &d;
      dynamic_cast<Derived*>(b); // Invalid
    }
    

    “向上投射”( static_cast转换为基类)对于static_castdynamic_cast都是有效的,并且也没有任何投射,因为“上投射”是隐式转换。

    定期演员

    这些演员也被称为C型演员。 C风格的转换基本上与尝试一系列C ++转换序列相同,并且可以在不考虑dynamic_cast情况下采用第一个可以工作的C ++转换。 不用说,这更强大,因为它结合了所有的const_caststatic_castreinterpret_cast ,但它也是不安全的,因为它不使用dynamic_cast

    另外,C风格转换不仅可以让你做到这一点,而且它们还允许你安全地转换到私有基类,而“等效” static_cast序列会给你一个编译时错误。

    有些人更喜欢C风格的演员,因为他们简洁。 我仅将它们用于数字转换,并且在涉及用户定义的类型时使用适当的C ++类型转换,因为它们提供更严格的检查。


    静态投射

    静态转换执行兼容类型之间的转换。 它类似于C风格的演员,但更具限制性。 例如,C风格的转换将允许一个整数指针指向一个字符。

    char c = 10;       // 1 byte
    int *p = (int*)&c; // 4 bytes
    

    由于这会产生指向分配内存1字节的4字节指针,因此写入此指针会导致运行时错误或覆盖某些相邻内存。

    *p = 5; // run-time error: stack corruption
    

    与C风格转换相反,静态转换将允许编译器检查指针和指针数据类型是否兼容,这允许程序员在编译期间捕获这个不正确的指针分配。

    int *q = static_cast<int*>(&c); // compile-time error
    

    重新演绎演员

    要强制转换指针,与C风格转换在后台执行相同的操作,将使用reinterpret强制转换。

    int *r = reinterpret_cast<int*>(&c); // forced conversion
    

    此演员处理某些不相关类型之间的转换,例如从一个指针类型到另一个不兼容的指针类型。 它将简单地执行数据的二进制拷贝而不改变基础位模式。 请注意,这种低级别操作的结果是系统特定的,因此不可移植。 如果无法完全避免,应谨慎使用。

    动态投射

    这个仅用于将对象指针和对象引用转换为继承层次结构中的其他指针或引用类型。 它是通过执行运行时检查指针指向目标类型的完整对象来确保指向的对象可以转换的唯一类型。 对于此运行时检查,对象必须是多态的。 也就是说,该类必须定义或继承至少一个虚拟功能。 这是因为编译器只会为这些对象生成所需的运行时类型信息。

    动态演员示例

    在下面的示例中,使用动态强制转换将MyChild指针转换为MyBase指针。 此派生到基础的转换成功,因为子对象包含完整的基础对象。

    class MyBase 
    { 
      public:
      virtual void test() {}
    };
    class MyChild : public MyBase {};
    
    
    
    int main()
    {
      MyChild *child = new MyChild();
      MyBase  *base = dynamic_cast<MyBase*>(child); // ok
    }
    

    下一个示例尝试将MyBase指针转换为MyChild指针。 由于Base对象不包含完整的Child对象,因此此指针转换将失败。 为了表明这一点,动态强制转换返回一个空指针。 这提供了一种方便的方式来检查运行时转换是否成功。

    MyBase  *base = new MyBase();
    MyChild *child = dynamic_cast<MyChild*>(base);
    
    
    if (child == 0) 
    std::cout << "Null pointer returned";
    

    如果引用被转换而不是指针,则动态转换将通过抛出bad_cast异常而失败。 这需要使用try-catch语句来处理。

    #include <exception>
    // …  
    try
    { 
      MyChild &child = dynamic_cast<MyChild&>(*base);
    }
    catch(std::bad_cast &e) 
    { 
      std::cout << e.what(); // bad dynamic_cast
    }
    

    动态或静态演员

    使用动态转换的优点在于,它允许程序员在运行时检查转换是否成功。 缺点是与执行此检查相关的性能开销。 出于这个原因,在第一个示例中使用静态转换会更可取,因为派生到基准转换永远不会失败。

    MyBase *base = static_cast<MyBase*>(child); // ok
    

    但是,在第二个示例中,转换可能成功或失败。 如果MyBase对象包含MyBase实例,它将失败,如果它包含MyChild实例,它将成功。 在某些情况下,这可能直到运行时才会被发现。 在这种情况下,动态投射比静态投射更好。

    // Succeeds for a MyChild object
    MyChild *child = dynamic_cast<MyChild*>(base);
    

    如果使用静态转换而不是动态转换来执行基于派生的转换,则转换不会失败。 它会返回一个指向不完整对象的指针。 解引用这样的指针会导致运行时错误。

    // Allowed, but invalid
    MyChild *child = static_cast<MyChild*>(base);
    
    // Incomplete MyChild object dereferenced
    (*child);
    

    Const施放

    这个主要用于添加或删除变量的const修饰符。

    const int myConst = 5;
    int *nonConst = const_cast<int*>(&myConst); // removes const
    

    虽然const转换允许改变常量的值,但这样做仍然是无效的代码,可能会导致运行时错误。 例如,如果常量位于只读存储器的一部分中,则可能发生这种情况。

    *nonConst = 10; // potential run-time error
    

    当一个函数接受一个非常量的指针参数时,即使它不修改指针,主要是使用const强制转换。

    void print(int *p) 
    {
       std::cout << *p;
    }
    

    该函数可以通过使用const转换来传递一个常量变量。

    print(&myConst); // error: cannot convert 
                     // const int* to int*
    
    print(nonConst); // allowed
    

    来源和更多的解释


    你应该看看文章C ++ Programming / Type Casting。

    它包含了所有不同类型演员的很好的描述。 以下摘自以上链接:

    const_cast会

    const_cast(expression)const_cast <>()用于添加/删除变量的const(ness)(或volatile)。

    的static_cast

    static_cast(expression)static_cast <>()用于在整数类型之间进行转换。 'eg'char-> long,int-> short等。

    静态转换也用于投射指向相关类型的指针,例如将void *转换为适当的类型。

    的dynamic_cast

    动态转换用于在运行时转换指针和引用,通常用于在继承链(继承层次结构)上向上或向下转换指针或引用。

    dynamic_cast的(表达)

    目标类型必须是指针或引用类型,并且表达式必须计算为指针或引用。 只有当表达式引用的对象类型与目标类型兼容且基类至少有一个虚拟成员函数时,动态转换才有效。 如果不是,并且被转换的表达式类型是一个指针,则返回NULL,如果引用上的动态转换失败,则引发bad_cast异常。 当它没有失败时,动态强制转换将目标类型的指针或引用返回到表达式引用的对象。

    reinterpret_cast的

    重新解释转换只是简单地将一种类型转换为另一种类型。 任何指针或整数类型都可以通过重新解释强制转换为任何其他类型,从而容易被滥用。 例如,通过重新解释强制转换,可以不安全地将一个整型指针转换为一个字符串指针。

    链接地址: http://www.djcxy.com/p/4861.html

    上一篇: Regular cast vs. static

    下一篇: How to resolve: "cast to pointer from integer of different size" warning in C code?