代码之家  ›  专栏  ›  技术社区  ›  Tommy Herbert

为什么使用静态_cast<int>(x)而不是(int)x?

  •  572
  • Tommy Herbert  · 技术社区  · 17 年前

    我听说 static_cast 功能型铸造应优先于C型铸造或简单功能型铸造。这是真的吗?为什么?

    9 回复  |  直到 6 年前
        1
  •  679
  •   Jarvis    7 年前

    static_cast<>() , reinterpret_cast<>() , const_cast<>() dynamic_cast<>() . 这四件事是完全不同的。

    A. 静态_cast<&燃气轮机;() 通常是安全的。语言中有一个有效的转换,或者有一个合适的构造函数使之成为可能。唯一有点冒险的时候是当你放弃继承类时;您必须确保该对象实际上是您声称的后代,方法是语言外部的(如对象中的标志)。A. 只要检查了结果(指针)或考虑了可能的异常(参考),就安全。

    A. 重新解释铸造<&燃气轮机;() 康斯特卡斯特<&燃气轮机;() )另一方面,这总是危险的。你告诉编译器:“相信我:我知道这看起来不像一个 foo

    第一个问题是,如果不查看大量分散的代码片段并了解所有规则,就几乎不可能判断C样式转换中会出现哪一个。

    class CDerivedClass : public CMyBase {...};
    class CMyOtherStuff {...} ;
    
    CMyBase  *pSomething; // filled somewhere
    

    CDerivedClass *pMyObject;
    pMyObject = static_cast<CDerivedClass*>(pSomething); // Safe; as long as we checked
    
    pMyObject = (CDerivedClass*)(pSomething); // Same as static_cast<>
                                         // Safe; as long as we checked
                                         // but harder to read
    

    但是,让我们看一下几乎相同的代码:

    CMyOtherStuff *pOther;
    pOther = static_cast<CMyOtherStuff*>(pSomething); // Compiler error: Can't convert
    
    pOther = (CMyOtherStuff*)(pSomething);            // No compiler error.
                                                      // Same as reinterpret_cast<>
                                                      // and it's wrong!!!
    

    正如您所看到的,如果不了解所有涉及的类,就很难区分这两种情况。

    第二个问题是C样式转换太难定位。在复杂表达式中,很难看到C样式转换。几乎不可能编写一个自动化工具,它需要定位C风格的铸件(例如搜索工具),而不需要完全的C++编译器前端。另一方面,很容易搜索“static\u cast<”或“reinterpret\u cast<”。

    pOther = reinterpret_cast<CMyOtherStuff*>(pSomething);
          // No compiler error.
          // but the presence of a reinterpret_cast<> is 
          // like a Siren with Red Flashing Lights in your code.
          // The mere typing of it should cause you to feel VERY uncomfortable.
    

    这意味着,C型演员不仅更加危险,而且要找到所有演员以确保其正确性要困难得多。

        2
  •  121
  •   Karl    17 年前

    一个实用的技巧:如果您计划整理项目,您可以在源代码中轻松搜索static_cast关键字。

        3
  •  93
  •   Community Mohan Dere    9 年前

    简言之 :

    1. static_cast<>() 提供编译时检查功能,C风格
    2. 容易被发现 任何地方都有C++源代码;相比之下,C_风格的演员更难被发现。
    3. 使用C++的转换可以更好地传达意图。

    更多解释

    静态强制转换在 兼容类型 . 信息技术 类似于C样式转换,但限制性更强。例如 C样式转换允许整数指针指向字符。

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

    因为这会导致一个4字节指针指向分配的1个字节 内存中,写入此指针将导致运行时错误或 将覆盖一些相邻的内存。

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

    编译器检查指针和指针对象数据类型是否正确 兼容,这允许程序员捕获此错误 编译期间的指针赋值。

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


    What is the difference between static_cast<> and C style casting

    Regular cast vs. static_cast vs. dynamic_cast

        4
  •  29
  •   Dusty Campbell    17 年前

    这个问题比仅仅使用威瑟静态类型转换或C样式转换更大,因为使用C样式转换时会发生不同的事情。C++的铸造操作符旨在使这些操作更加明确。

    int i;
    double d = (double)i;                  //C-style cast
    double d2 = static_cast<double>( i );  //C++ cast
    

    class A {};
    class B : public A {};
    
    A* a = new B;
    B* b = (B*)a;                                  //(1) what is this supposed to do?
    
    char* c = (char*)new int( 5 );                 //(2) that weird?
    char* c1 = static_cast<char*>( new int( 5 ) ); //(3) compile time error
    

    在本例中(1)可能是可以的,因为A指向的对象实际上是B的实例。但是如果在代码中的那个点上您不知道A实际指向什么呢?(2) 也许完全合法(您只想查看整数的一个字节),但也可能是一个错误,在这种情况下,错误会很好,如(3)。CC++铸造操作符旨在通过在可能的时候提供编译时间或运行时错误来在代码中公开这些问题。

    因此,对于严格的“值转换”,您可以使用静态转换。如果您想要运行时多态转换指针,请使用动态转换。如果您真的想忘记类型,可以使用reintrepret_cast。把康斯特扔出窗外就是康斯特·卡斯特。

    它们只是使代码更加明确,这样看起来您知道自己在做什么。

        5
  •  26
  •   cbuchart    9 年前

    static_cast 意味着你不能意外地 const_cast reinterpret_cast

        6
  •  8
  •   JohnMcG    17 年前
    1. 允许在中轻松找到类型转换 您的代码使用grep或类似工具
    2. 明确了是哪一种 你正在做的演员,和参与 如果你只想抛弃 const ness,那么您可以使用 const_cast,这将不允许您 进行其他类型的转换。
    3. 演员天生丑陋——你也是 一个程序员正在否决 密码你是在对警察说 “我比你知道得多。” 表演演员阵容应该是一种挑战 中度疼痛的事情要做,和 许多问题。

    Effective C++ 介绍

        7
  •  7
  •   Pitarou    12 年前

    当你写作时 (bar) foo (相当于 reinterpret_cast<bar> foo 如果您没有提供类型转换运算符),那么您是在告诉编译器忽略类型安全性,只需按照要求执行即可。

    当你写作时 static_cast<bar> foo 您要求编译器至少检查类型转换是否有意义,对于整型,请插入一些转换代码。


    编辑2014-02-26

    我在5年多前写下了这个答案,但我弄错了。(见评论)但它仍然获得了更多的选票!

        8
  •  6
  •   Konrad    17 年前

    reinterpret_cast允许整数到指针类型的转换,但如果使用不当,则可能不安全。

    static_cast为数字类型提供了良好的转换,例如从as enum到int或int到float或任何您确信类型的数据类型。它不执行任何运行时检查。

    还有一些其他的,但这些是你会遇到的主要问题。

        9
  •  4
  •   prakash    17 年前

    除了操纵指向类的指针外,static_cast还可用于执行类中显式定义的转换,以及执行基本类型之间的标准转换:

    double d = 3.14159265;
    int    i = static_cast<int>(d);