Why Use Static_Cast≪Int≫(X) Instead of (Int)X

Why use static_castint(x) instead of (int)x?

The main reason is that classic C casts make no distinction between what we call static_cast<>(), reinterpret_cast<>(), const_cast<>(), and dynamic_cast<>(). These four things are completely different.

A static_cast<>() is usually safe. There is a valid conversion in the language, or an appropriate constructor that makes it possible. The only time it's a bit risky is when you cast down to an inherited class; you must make sure that the object is actually the descendant that you claim it is, by means external to the language (like a flag in the object). A dynamic_cast<>() is safe as long as the result is checked (pointer) or a possible exception is taken into account (reference).

A reinterpret_cast<>() (or a const_cast<>()) on the other hand is always dangerous. You tell the compiler: "trust me: I know this doesn't look like a foo (this looks as if it isn't mutable), but it is".

The first problem is that it's almost impossible to tell which one will occur in a C-style cast without looking at large and disperse pieces of code and knowing all the rules.

Let's assume these:

class CDerivedClass : public CMyBase {...};
class CMyOtherStuff {...} ;

CMyBase *pSomething; // filled somewhere

Now, these two are compiled the same way:

CDerivedClass *pMyObject;
pMyObject = static_cast<CDerivedClass*>(pSomething); // Safe; as long as we checked

pMyObject = (CDerivedClass*)(pSomething); // Same as static_cast<>
// Safe; as long as we checked
// but harder to read

However, let's see this almost identical code:

CMyOtherStuff *pOther;
pOther = static_cast<CMyOtherStuff*>(pSomething); // Compiler error: Can't convert

pOther = (CMyOtherStuff*)(pSomething); // No compiler error.
// Same as reinterpret_cast<>
// and it's wrong!!!

As you can see, there is no easy way to distinguish between the two situations without knowing a lot about all the classes involved.

The second problem is that the C-style casts are too hard to locate. In complex expressions it can be very hard to see C-style casts. It is virtually impossible to write an automated tool that needs to locate C-style casts (for example a search tool) without a full blown C++ compiler front-end. On the other hand, it's easy to search for "static_cast<" or "reinterpret_cast<".

pOther = reinterpret_cast<CMyOtherStuff*>(pSomething);
// No compiler error.
// but the presence of a reinterpret_cast<> is
// like a Siren with Red Flashing Lights in your code.
// The mere typing of it should cause you to feel VERY uncomfortable.

That means that, not only are C-style casts more dangerous, but it's a lot harder to find them all to make sure that they are correct.

static_castunsigned vs static_castunsigned int [duplicate]

Is there ANY difference?

unsigned int has 4 more characters than unsigned. There are no other differences.

And also, is there any peformance differences?

No.

static_castint(foo) vs. (int)foo

The difference is that (int)foo can mean half a dozen different things.
It might be a static_cast (convert between statically known types), it might be a const_cast (adding or removing const-ness), or it might be a reinterpret_cast (converting between pointer types)

The compiler tries each of them until it finds one that works. Which means that it may not always pick the one you expect, so it can become a subtle source of bugs.

Further, static_cast is a lot easier to search for or do search/replace on.

What is the difference between static_cast and C style casting?

C++ style casts are checked by the compiler. C style casts aren't and can fail at runtime.

Also, c++ style casts can be searched for easily, whereas it's really hard to search for c style casts.

Another big benefit is that the 4 different C++ style casts express the intent of the programmer more clearly.

When writing C++ I'd pretty much always use the C++ ones over the the C style.

Using static_cast over compound operators

I think you're misunderstanding the function of static_cast.

static_cast will (if possible) convert a value to another type, and give you a resulting rvalue of the new type1. An rvalue is not something you can assign to2 (unlike an lvalue, which is what you're seeing in your error message).

In C++ a variable's type is given once and only once during the declaration. For that variable's entire lifetime it'll be of the type it was declared (Note this is different from weaker typed languages like Python or JavaScript).


In reply to your example, note that no variables are changing their types.

average = static_cast<double>(total) / count;

average was declared as a double, and it remains a double. The magic here is that you're casting total to double. So static_cast<double>(total) gives you a double with the equivalent value as the integer total (but this is no longer total! It's now a temporary unnamed double). You then divide that unnamed double by count, and assign the result to average.


1. Except in the case where the type to convert to is a reference type. (thanks Brian!)

2. For native types. "Any class type rvalue can be assigned to unless you explicitly forbid it." (Thanks Nathan!)

Regular cast vs. static_cast vs. dynamic_cast [duplicate]

static_cast

static_cast is used for cases where you basically want to reverse an implicit conversion, with a few restrictions and additions. static_cast performs no runtime checks. This should be used if you know that you refer to an object of a specific type, and thus a check would be unnecessary. Example:

void func(void *data) {
// Conversion from MyClass* -> void* is implicit
MyClass *c = static_cast<MyClass*>(data);
...
}

int main() {
MyClass c;
start_thread(&func, &c) // func(&c) will be called
.join();
}

In this example, you know that you passed a MyClass object, and thus there isn't any need for a runtime check to ensure this.

dynamic_cast

dynamic_cast is useful when you don't know what the dynamic type of the object is. It returns a null pointer if the object referred to doesn't contain the type casted to as a base class (when you cast to a reference, a bad_cast exception is thrown in that case).

if (JumpStm *j = dynamic_cast<JumpStm*>(&stm)) {
...
} else if (ExprStm *e = dynamic_cast<ExprStm*>(&stm)) {
...
}

You can not use dynamic_cast for downcast (casting to a derived class) if the argument type is not polymorphic. For example, the following code is not valid, because Base doesn't contain any virtual function:

struct Base { };
struct Derived : Base { };
int main() {
Derived d; Base *b = &d;
dynamic_cast<Derived*>(b); // Invalid
}

An "up-cast" (cast to the base class) is always valid with both static_cast and dynamic_cast, and also without any cast, as an "up-cast" is an implicit conversion (assuming the base class is accessible, i.e. it's a public inheritance).

Regular Cast

These casts are also called C-style cast. A C-style cast is basically identical to trying out a range of sequences of C++ casts, and taking the first C++ cast that works, without ever considering dynamic_cast. Needless to say, this is much more powerful as it combines all of const_cast, static_cast and reinterpret_cast, but it's also unsafe, because it does not use dynamic_cast.

In addition, C-style casts not only allow you to do this, but they also allow you to safely cast to a private base-class, while the "equivalent" static_cast sequence would give you a compile-time error for that.

Some people prefer C-style casts because of their brevity. I use them for numeric casts only, and use the appropriate C++ casts when user defined types are involved, as they provide stricter checking.



Related Topics



Leave a reply



Submit