what is static_cast for?

Started by
9 comments, last by Goishin 16 years, 11 months ago
Hi all, I'm trying to understand the value of using static casting versus regular c style casting. For example: static_cast<int>myDoubleVar vs: (int)myDoubleVar What's the difference? Don't you get the same thing? - Goishin
Advertisement
Quote:Original post by Goishin
Hi all, I'm trying to understand the value of using static casting versus regular c style casting.

For example:
static_cast<int>myDoubleVar

vs:
(int)myDoubleVar

What's the difference? Don't you get the same thing?

- Goishin


Mostly, yes.
the C-style cast does what static_cast does, *and a lot more*.
it also does what reinterpret_cast does, and what const_cast does.
In other words, when you use a C-style cast, it's not always easy to figure out what kind of cast is actually performed.
With static_cast, you only ask the compiler to generate a, well, static cast. It can't be used to convert from, say, float* to int* because that's a reinterpret-cast.

The point is that a cast is not just a cast. static_cast and reinterpret_cast are handled very differently by the compiler, so why shouldn't the difference be visible?


Oh, and another difference. static_cast is intentionally ugly/awkward to write. That's because casts are supposed to be ugly. You're not supposed to use them unless you really have to. Making them look ugly helps people stay away from them ;)
They're also easier to search for and can be easily spotted when reading over your code.
(type) will use any combination of static_cast, const_cast and reinterpet_cast to cast to the desired type. static_cast restricts it to just casts valid for use with static_cast.
static_cast is *much* easier to search for in code. If you think a bug may be because of an incorrect cast, search and replace becomes much quicker. Granted this doesn't happen much with static_cast, but with const_cast and reinterpret_cast this is a large issue.

Its nice to be able to tell instantly that my code doesn't use unsafe casts as searching for const_cast and reinterpret_cast doesn't return any results, and I never use C casts anymore.

Its also a bit more obvious, prevents me having to write code like this (I often place excessive brackets to ensure the compiler knows what I'm on about, but I'm just strange [smile]):

((float)foo)/bar vs static_cast<float>(foo)/bar
Ok, now I'm REALLY confused. What's a static_cast for? And a reinterpret_cast, and a const_cast?

I think I might understand a reinterpret_cast as interpreting one type for another type. I.E. a double as a float as an int as a short(with loss of precision along the way). But what about the other two (or three if I got reinterpret_cast wrong)?

- Goishin
Here's a link to a page that briefly explains the casting:

http://www.cplusplus.com/doc/tutorial/typecasting.html

Hope that helps...
Quote:Original post by Goishin
Ok, now I'm REALLY confused. What's a static_cast for? And a reinterpret_cast, and a const_cast?

I think I might understand a reinterpret_cast as interpreting one type for another type. I.E. a double as a float as an int as a short(with loss of precision along the way). But what about the other two (or three if I got reinterpret_cast wrong)?

- Goishin


static_cast means try to convert one type to another using rues the compiler is allowed. For example static_cast<int>(1.2f) is 1. static_cast<std::string>("foo") is a std::string containing foo. static_cast<const char *>(someStdString) is an error, as is static_cast<int*>(42) because the compiler cannot perform such a conversion.

In general, a static_cast can be used anywhere you could use an unnamed temporary:

static_cast<Foo>(bar)
Foo anonymous_name_we_cannot_see = bar

Just be careful when using pointers and static_cast, it allows casts that are incorrect:
class Foo {};class Bar : public Foo {};int main(){   Foo foo;   Bar *b = static_cast<Bar *>(foo); // compiles!}



reinterpret_cast<> means don't do *any* conversion. It means treat the bit pattern in the brackets as if it were a pointer to a different type. It basically means "STFU compiler I know what I'm doing". As such, if you do not know what you are doing don't use it. reinterpret_cast<int*>(42) may compile, but if I ever catch you using it... just don't use it. [smile]


const_cast<> is like reinterpret cast, in some ways. It can "remove" const from a variable. Not really, but again it shuts the compiler complaining while the programmer abuses the language. const_cast<char*>("foo") will compile
  • . Sometimes you may have a const argument to a function, but you know the *actual* argument passed is non-const, you could use const_cast to rid yourself of the const. Its one of those things that should never be used, its unsafe. The only time I could ever see a use for it is interacting with an API which uses const incorrectly. But even then you'd better have a damn good excuse.


    Even though you didn't mention it, there is another C++ cast, dynamic_cast. dynamic_cast casts between pointers and references of classes in an inheritance hierarchy. It can do downcasts (convert a Super* to a SubClass* ), it will return 0 on an incorrect pointer downcast( incorrect meaning the Super* was not of type SubClass* ), or throw a std::bad_cast on an incorrect reference cast.

    class Base {};class Derived : public Base {};class OtherDerived : public Base {};void foo( Base *b ) {    Derived *d = dynamic_cast<Derived*>(b);    if( d ) {       std::cout << "passed a Derived object\n";    }    OtherDerived *o = dynamic_cast<OtherDerived *>(b);    if( o ) {       std::cout << "passed an OtherDerived object\n";    }}// or using references:void foo( Base &b ) {    try {       Derived &d = dynamic_cast<Derived &>(b);       std::cout << "passed a Derived object\n";    }    catch( std::bad_cast ) {} // do nothing    try {       OtherDerived &o = dynamic_cast<OtherDerived &>(b);       std::cout << "passed an OtherDerived object\n";    }     catch( std::bad_cast ) {} // do nothing}


    However, use of dynamic_cast, while safe (as in it should always work) is indicative of incorrect design. There are usually far better ways of writing equivalent code.


    [*]
  • Ok, I think I got it.

    Thanks rip-off and SAE Superman, those two answers did the trick. I think I'm still having a little difficulty with static_cast, but I think I just need to let it percolate a little bit. The other three I've got a pretty good handle on.
    Ok, how do you mark this thread resolved? I've seen some other threads marked resolved on these boards so I know you can do it, I just can't figure out how...

    - Goishin
    Quote:Original post by Goishin
    Ok, how do you mark this thread resolved? I've seen some other threads marked resolved on these boards so I know you can do it, I just can't figure out how...

    - Goishin


    You don't. Someone more knowledgeable may come along and add more to the topic, or they may correct mistakes in posts here. Or someone else struggling with the topic may post for clarification on a particular point.

    I believe you may be able to change the title of a thread by editing the original post, but as I said please don't.

    There is a potential for more discussion, so don't artificially end the thread.

    This topic is closed to new replies.

    Advertisement