Why use static_cast(x) instead of (int)x?

前端 未结 9 1761
滥情空心
滥情空心 2020-11-22 02:38

I\'ve heard that the static_cast function should be preferred to C-style or simple function-style casting. Is this true? Why?

相关标签:
9条回答
  • 2020-11-22 02:56

    The main reason is that classic C casts make no distinction between what we call static_cast<>(), reinterpret_cast<>(), const_cast<>(), and dynamic_cast<>(). These four things are completely different.

    A static_cast<>() is usually safe. There is a valid conversion in the language, or an appropriate constructor that makes it possible. The only time it's a bit risky is when you cast down to an inherited class; you must make sure that the object is actually the descendant that you claim it is, by means external to the language (like a flag in the object). A dynamic_cast<>() is safe as long as the result is checked (pointer) or a possible exception is taken into account (reference).

    A reinterpret_cast<>() (or a const_cast<>()) on the other hand is always dangerous. You tell the compiler: "trust me: I know this doesn't look like a foo (this looks as if it isn't mutable), but it is".

    The first problem is that it's almost impossible to tell which one will occur in a C-style cast without looking at large and disperse pieces of code and knowing all the rules.

    Let's assume these:

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

    Now, these two are compiled the same way:

    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
    

    However, let's see this almost identical code:

    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!!!
    

    As you can see, there is no easy way to distinguish between the two situations without knowing a lot about all the classes involved.

    The second problem is that the C-style casts are too hard to locate. In complex expressions it can be very hard to see C-style casts. It is virtually impossible to write an automated tool that needs to locate C-style casts (for example a search tool) without a full blown C++ compiler front-end. On the other hand, it's easy to search for "static_cast<" or "reinterpret_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.
    

    That means that, not only are C-style casts more dangerous, but it's a lot harder to find them all to make sure that they are correct.

    0 讨论(0)
  • 2020-11-22 03:00

    C Style casts are easy to miss in a block of code. C++ style casts are not only better practice; they offer a much greater degree of flexibility.

    reinterpret_cast allows integral to pointer type conversions, however can be unsafe if misused.

    static_cast offers good conversion for numeric types e.g. from as enums to ints or ints to floats or any data types you are confident of type. It does not perform any run time checks.

    dynamic_cast on the other hand will perform these checks flagging any ambiguous assignments or conversions. It only works on pointers and references and incurs an overhead.

    There are a couple of others but these are the main ones you will come across.

    0 讨论(0)
  • 2020-11-22 03:01
    1. Allows casts to be found easily in your code using grep or similar tools.
    2. Makes it explicit what kind of cast you are doing, and engaging the compiler's help in enforcing it. If you only want to cast away const-ness, then you can use const_cast, which will not allow you to do other types of conversions.
    3. Casts are inherently ugly -- you as a programmer are overruling how the compiler would ordinarily treat your code. You are saying to the compiler, "I know better than you." That being the case, it makes sense that performing a cast should be a moderately painful thing to do, and that they should stick out in your code, since they are a likely source of problems.

    See Effective C++ Introduction

    0 讨论(0)
提交回复
热议问题