I use C-style casts in my 15K LOC C++ project, 90% of the times for casts between child and base classes.
Even when I read that it is bad to use them, and that they can result in severe errors, as they are not type safe as the C++ casts, I still feel perfectly fine and comfortable with using them.
I have not experienced a single bug in my project so far that was caused by, for example, an accidentally mistyped C-Style cast - really.
There are two main reasons I have not been using them:
My questions:
I use as good as all other advantages C++ offers me, from OOP including virtual and abstract base classes, namespaces, the STL, and so on, just not the new type casting syntax. The argument "Why aren't you just using C then?" doesn't work for me.
static_cast<>() gives you a compile time checking ability, C-Style cast doesn't. static_cast<>() is more readable and can be spotted easily anywhere inside a C++ source code, C_Style cast is'nt. Intentions are conveyed much better using C++ casts.
C-style casts can be used to convert any type into any other type, potentially with unsafe results (such as casting an integer into a pointer type). (<type>)<value> This example casts an int to a double for the purpose of avoiding truncation due to integer division: double result = (double)4/5; Popular pages.
Static casts are only available in C++. Static casts can be used to convert one type into another, but should not be used for to cast away const-ness or to cast between non-pointer and pointer types.
The main advantage of the C++-style casts is, as you've mentioned, the type safety. Each cast in C++ handles one specific sort of conversion (or a family of related conversions) and so the compiler can go and check that you're not accidentally doing more conversions that you intended, or a sequence of conversions that fundamentally isn't safe.
One thing to think about is that while it's great that you feel comfortable using C-style casts, and while it's great that you haven't made any mistakes with them, other people working on the code base might not be as facile with these casts as you are. Using the casting operators makes the code more self-documenting. If you have a C-style cast somewhere, someone else reading the code might not be able to immediately infer what it is that you're doing. If they see something like
T* ptr = (T*) var;
They might not immediately be able to tell if this is
const
ness off of var
While they can probably glean this from context, it's a lot more obvious what's going on if you use a cast like
T* ptr = static_cast<T*>(var);
or
T* ptr = const_cast<T*>(var);
Another reason to prefer the C++-style casting operators is that they make the code more resilient to change. For example, suppose I have this function:
void DoSomething(Base* ptr) { Derived* derived = (Derived *) ptr; DoSomethingElse(derived); }
Now, suppose that I realize that this function isn't supposed to make any changes to its argument, so I decide to mark it const
. For example:
void DoSomething(const Base* ptr) { Derived* derived = (Derived *) ptr; DoSomethingElse(derived); }
But now we have a problem - my C-style cast which used to just do a downcast now also strips off const
ness. This can lead to an easy bug where DoSomethingElse
mutates the pointer I pass in, even though the DoSomething
method itself promises not to do this. If instead I wrote this code as
void DoSomething(Base* ptr) { Derived* derived = static_cast<Derived *>(ptr); DoSomethingElse(derived); }
And then change the code by adding const
:
void DoSomething(const Base* ptr) { Derived* derived = static_cast<Derived *>(ptr); DoSomethingElse(derived); }
Now I'll get a compiler error telling me that my old cast is broken, which can lead me to discover that there is a logical error in the code (namely, that DoSomethingElse
mutates its argument, so I can't naively make ptr
a pointer-to-const
.
So in short, using the C++ casting operators makes the code more readable and more maintainable. It makes the logic behind the code more explicit. And it makes the code less bug-prone by having the compiler catch errors either as you're making them or later on as you go back and change old code. I would recommend trying to use C++-style casting operators in the future for these main reasons.
As for whether you should go back and try to replace your current C-style casts with C++-style casts, that's really up to you. As an exercise, I'd suggest doing it just to practice learning what sorts of casts you're using. Plus, you might find a logic error in there, which would make the search worth your while!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With