The first two, (MyType)foo
and MyType(foo)
, have the same meaning. What the meaning is depends a lot on MyType
and the type of foo
. So for example:
((int)1.0); // a static_cast
int i = 0;
((char*)&i); // a reinterpret_cast
const int j = 0;
((int*)&j); // a const_cast
((char*)&j); // a combination of a const_cast and a reinterpret_cast
typedef char *CharPtr;
CharPtr(&j); // a C-style cast, same as ((CharPtr)&j) or ((char*)&j)
So the reason C-style casts are not preferred is that C-style casts do a lot of different things. C++ provides means to distinguish between them. In a lot of cases that makes it easier to understand the code, especially once you're writing generic code in C++ and the types are less obvious than they typically are in C.
So that's why static_cast
etc are preferred in C++ -- they lay out explicitly for the reader something that might otherwise be difficult for them to work out for themselves. static_cast
also does a few different things, by the way, so in principle you might want even more different casts. But static_cast
at least does less than a C-style cast.
Functional-style casts with one argument are C-style casts. They are explicitly defined in the standard to mean exactly the same thing, in all cases.
Now, there are some cases where you might accept a C-style cast when written in the functional syntax but not when written with the C cast syntax. This is generally when the destination type is a class and it's obvious which constructor will be called. In a case like that, std::vector<int>(0)
is shorter than static_cast<std::vector<int>>(0)
, and generally clearer since it can be read as a constructor call. But it still has the same "dangers" as writing (std::vector<int>)0
. If you were to write every conversion that way then eventually you'd accidentally remove const
from a pointer type.