are static cast and (int) the same thing?

I can't understand why static_cast, if all the same can be done by directly specifying the type.

 18
Author: αλεχολυτ, 2013-03-06

3 answers

A very hackneyed topic. Why do you need it? well, because they have slightly different behavior. Here is a very good article that describes the difference.

Here is a quote with the answer to the question

What C-style type casting does: tries to use static_cast, if it fails, uses reinterpret_cast. Then, if necessary, use const_cast.

Another argument - all sorts of static_cast are easier to find by searching.

Two more links to the threads where this is actively discussed - habr and rsdn.org.

 18
Author: KoVadim, 2017-02-06 07:51:43

The problem is that () - type casting can mean a million different things that you don't even know about, depending on the context.

First, it performs the conversion of arithmetic types. If you need int from double, it calculates the integer part. If you need char from long, it discards significant digits.

Second, it discards the const and volatile specifiers. Unnoticed by you.

Third, it converts int to pointer and back.

Fourth, it transforms pointers up and down the inheritance hierarchy.

Fifth, it converts pointers as reinterpret_cast, focusing on the bit representation.

In contrast, static_cast only does arithmetic type conversion (for arithmetic types) and pointer conversion up and down the inheritance hierarchy (for pointers). [You can still cast completely "unfamiliar" types to each other in two steps, through void*, but this already needs to be done explicitly and cannot be done by mistake. Here is the full list of rules.]

In many cases, you don't need the insane power of ()-casting, because it can hide errors. Examples:

void f(char *str);

void g(const _TCHAR *txt)
{
    f((char*)txt);               // компилируется
    f(static_cast<char*>(txt));  // не компилируется
}

Here, the call probably shouldn't compile, because the f function expects a single-byte string, and is probably not ready to work with wchar_t*. If the function f can work with such strings, you can use reinterpret_cast. for the ()-cast case, you don't have the ability to distinguish between these cases.

void f(char *str);

void g(const char *txt)
{
    f((char*)txt);               // компилируется
    f(static_cast<char*>(txt));  // не компилируется
}

Here, again, the call should not be compiled, because the f function has the right to modify the string, and the characters in txt cannot be modified.

Of course, in such simple examples, the problem is visible to the "naked eye". But if the function g is a template, and the exact type txt is unknown at the point of the function definition, it is much more difficult for you to catch such errors. In this case, static_cast will allow catch them at the compilation stage, without causing the program to crash.

 16
Author: VladD, 2017-02-06 09:32:17

An expression like (T) is described in chapter 5.4 Explicit type conversion (cast notation) [expr. cast].

It tries the following transformations in turn

  • const_cast
  • static_cast
  • static_cast and then const_cast
  • reinterpret_cast
  • reinterpret_cast and then const_cast

At the same time, for static_cast, the restriction on the visibility of the base class is removed when converting between pointers/references to the descendant classes and base classes. (As well as when transformations between pointers to class members).

class Base {};
class Derived : private Base {};
Derived* d = new Derived();

//static_cast<Base*>(d); // не скомпилируется: Base недоступна (private)
Base* b = (Base*)d; // OK

//static_cast<Derived*>(b); // не скомпилируется: Base недоступна (private)
Derived* d2 = (Derived*)b; // OK

If multiple conversion options are possible at the same time, the code is not compiled. (For example, in the case of multiple inheritance, there may be two base classes with the same type)

You can convert incomplete class types. At the same time, the standard does not specify which caste will be made, static_cast or reinterpret_cast.

struct X;
struct Y;
X* blind_cast(Y* y) {
    //return static_cast<X*>(y); // не скомпилируется: неполные типы
    return (X*)y; // OK
}

If we define these types

struct Base1 { int some; };
struct X {};
struct Y : Base1, X {};

Then the expression static_cast<X*>(y) == blind_cast(y) can be as true, and false:

  • if the compiler sees the full type definitions at the time of code generation, it will do static_cast,
  • if blind_cast is compiled separately, then the compiler will not see the full type definitions and will do reinterpret_cast, then the result of blind_cast will actually point to Base1, and the comparison will output false.
 7
Author: Abyx, 2017-02-07 07:12:55