I can not understand why static_cast , if everything can be done with the help of a direct type indication.

  • another question to cast dynamic_cast, there is such a feature. Der2 der2 = new Der2; Der der = dynamic_cast <Der *> (der2); Der and Der2 are not descendants or are, in general, then I try to make der-> Der_2 method_class, and it’s impossible, then why the transformation, what it gives, maybe I’m dumb, but I would still like to know, thanks. - fortunado
  • one
    Well, your object is n't really Der , right? And what do you expect - that the dynamic_cast will pull the object of the Der class over the object of the Der2 class from the Der2 ? If your object is actually a Der instance, then the dynamic_cast will work. By the way, you have a typo: you need Der * pder = dynamic_cast <Der *> (& der2); because dynamic_cast works with pointers. - VladD
  • thanks sort of figured out) - fortunado

3 answers 3

Very hackneyed topic. Why do you need? Well, because they have slightly different behavior. There is a very good article that describes the difference.

Here is a quote to answer the question

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

One more argument - any static_cast easier to search by search.

Two more links to threads where this is being actively discussed are Habr and rsdn.org .

  • one
    Between static_cast and (int) there are obviously more minuses of static_cast , since the context of the arithmetic operation itself is lost if such long entities are involved in them. I do not support the patient enthusiasm in using such obvious castes right and left. Beginners can be understood - interest, but the abuse of toppers by such practice speaks only of their immaturity. - mega

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

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

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

Third, it converts an int to a pointer and vice versa.

Fourth, it translates pointers up and down along the inheritance hierarchy.

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

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

In many cases, you don't need the insane power of the () cast, 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 most likely should not compile because the f function expects a one-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 case of () -quot, you do not 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 function f 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 pattern, and the exact type of txt 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 static_cast to catch them at compile time, without causing the program to crash.

  • 6
    Good answer. - But one can say the following: all C ++ type conversions are insurance for those who write according to the principle - “I'll write these letters — will it work?”. And the correct approach is “don't know, don't touch”. - avp
  • 2
    static_cast does only the conversion of arithmetic types (for arithmetic types) and the conversion of pointers along the inheritance hierarchy (for pointers) - IAZ
  • @IAZ: partially: ideone.com/wkpEhT Thanks, corrected. - VladD
  • @VladD: static_cast for pointers works "on trust" and does not do any checks, i.e. You can bring any pointers to each other. It only checks for the fact that one class is inherited from another, but not the object itself! - IAZ
  • @avp: "do not know - do not touch" - very correctly, otherwise undefined behavior is almost inevitable. - VladD

An expression of the form (T) 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, static_cast removes the restriction on the visibility of the base class during conversions between pointers / references to descendants and base classes. (And also when converting between pointers to members of classes).

 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 several transformations are possible at the same time, the code will not compile. (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 indicate 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 {}; 

That expression static_cast<X*>(y) == blind_cast(y) can be either true or false :

  • if at the time of code generation the compiler sees the full type definitions, then it will make static_cast ,
  • if blind_cast compiled separately, then the compiler does not see the full type definitions and does a reinterpret_cast , then the blind_cast result will actually point to Base1 , and the comparison Base1 false .
  • Something I suspect that an empty structure during inheritance will not move anything. Throw something int into it ... - Qwertiy
  • Yes, compilers do an empty base optimization. - Abyx