I can’t understand why static_cast
, if you can do the same using direct type casting.
Answer 1, authority 100%
This is a very hackneyed topic. Why do you need it? well, because they have a little different behavior. There is a very good article here that describes the difference.
Here is a quote with an answer to the question
What the C-style cast does: tries to use
static_cast
, if it fails, usesreinterpret_cast
. Further usesconst_cast
if needed.
One more argument – any static_cast
is easier to find with a search.
Two more links to threads where this is actively discussed – habr and rsdn.org .
Answer 2, authority 89%
The problem is that ()
casting can mean a million different things that you don’t even know about, depending on the context.
First, it performs arithmetic type conversions. If you want int
from double
, it calculates the integer part. If you want char
from long
, it strips off significant digits.
Second, it strips off the const
and volatile
specifiers. Unbeknownst to you.
Third, it converts int
to and from a pointer.
Fourth, it transforms pointers up and down the inheritance hierarchy.
Fifth, it converts pointers as reinterpret_cast
based on bit representation.
In contrast, static_cast
does only conversion of arithmetic types (for arithmetic types) and conversion of pointers up and down the inheritance hierarchy (for pointers). [You can still cast completely “unfamiliar” types to each other in two steps, via void *
, but this already needs to be done explicitly and cannot be done by mistake. Here is complete list of rules .]
In many cases, you don’t need the insane power of ()
ghosting, because it can hide errors. Examples:
void f (char * str);
void g (const _TCHAR * txt)
{
f ((char *) txt); // compiles
f (static_cast & lt; char * & gt; (txt)); // does not compile
}
The call here most likely shouldn’t compile because the f
function expects a single-byte string and is probably not ready to work with wchar_t *
. If the f
function can work with such strings, you can use reinterpret_cast
. For the case of ()
-casting, you have no way of distinguishing between these cases.
void f (char * str);
void g (const char * txt)
{
f ((char *) txt); // compiles
f (static_cast & lt; char * & gt; (txt)); // does not compile
}
Here again, the call should not compile, 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 of txt
is not known 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 you to catch them even at the compilation stage, without causing the program to crash.
Answer 3, authority 39%
An expression of the form (T)
is described in chapter 5.4 Explicit type conversion (cast notation) [expr.cast] .
It tries the following transforms in turn
const_cast
static_cast
static_cast
and thenconst_cast
reinterpret_cast
reinterpret_cast
and thenconst_cast
This removes the restriction on the visibility of the base class for conversions between pointers / references to descendant classes and base classes for static_cast
. (And also when converting between pointers to class members).
class Base {};
class Derived: private Base {};
Derived * d = new Derived ();
// static_cast & lt; Base * & gt; (d); // will not compile: Base is not available (private)
Base * b = (Base *) d; // OK
// static_cast & lt; Derived * & gt; (b); // will not compile: Base is not available (private)
Derived * d2 = (Derived *) b; // OK
If several conversions are possible at the same time, then 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 cast will be made, static_cast
or reinterpret_cast
.
struct X;
struct Y;
X * blind_cast (Y * y) {
// return static_cast & lt; X * & gt; (y); // won't compile: incomplete types
return (X *) y; // OK
}
If we define these types
struct Base1 {int some; };
struct X {};
struct Y: Base1, X {};
That expression static_cast & lt; X * & gt; (y) == blind_cast (y)
can be either true
or false
:
- if at the time of code generation the compiler sees the complete type definitions, then it will
static_cast
, - if
blind_cast
is compiled separately, then the compiler will not see the full type definitions and willreinterpret_cast
, then the result ofblind_cast
will actually point toBase1
, and the comparison will returnfalse
.