I can not understand why static_cast
, if everything can be done with the help of a direct type indication.
3 answers
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 usesreinterpret_cast
. Further, if necessary, it usesconst_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 .
- oneBetween 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.
- 6Good 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
- 2static_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 thenconst_cast
reinterpret_cast
reinterpret_cast
and thenconst_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 areinterpret_cast
, then theblind_cast
result will actually point toBase1
, and the comparisonBase1
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
Der
, right? And what do you expect - that thedynamic_cast
will pull the object of theDer
class over the object of theDer2
class from theDer2
? If your object is actually aDer
instance, then thedynamic_cast
will work. By the way, you have a typo: you need Der * pder = dynamic_cast <Der *> (& der2); becausedynamic_cast
works with pointers. - VladD