If I use C-Style casts in my C++ project, is it worth refactoring to C++ casts?
c++, casting, refactoring
Solution
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
- A cast from a base class to a derived class or the other way around.
- A cast to strip `const`ness off of `var`
- A cast from an integral type to a pointer.
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!
Problem
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: - I didn't know enough about them yet - I didn't like their syntax, they are more verbose and harder to read for me My questions: - (Why) Should I refactor my project to use C++-style casts? - Why should I use C++-style casts for my future projects? 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.