![]() |
| | #1 |
| Registered User Join Date: Apr 2005
Posts: 1,342
| |
| Queatrix is offline |
| | #2 |
| Cat without Hat Join Date: Apr 2003
Posts: 8,439
| Terminology: () is a C-style cast, *_cast is the C++-style cast. 1) Lack of differentiation. What if the C-style your cast will do whatever is necessary to achieve the target. If you meant to truncate a double to an int, it will do that. If you meant to cast a pointer to an integral type, it will do that too. If you mean to expand a short into an int explicitly to resolve ambiguity, it will do that. And if you mean to remove a const qualifier from a pointer because of a legacy function that isn't const-correct, it will do that. The C++-style has different keywords for different tasks. If you do a simple, rather safe cast, such as promoting short to int or truncating a double to int, you can use static_cast. Try anything more complex with it, and the compiler will complain. This ensures you don't accidently cast to some weird type when all you meant to do is truncate. E.g. look at this code: Code: void foo(double *val)
{
int v = *val;
}
Code: void foo(double *val)
{
int v = (int)val;
}
C++-style, you would have done this: Code: void foo(double *val)
{
int v = static_cast<int>(val);
}
The second cast operator, const_cast, applies to our last example. It will cast the const and volatile modifiers from and to types. (Of course, the addition of them is implicit, so they're rarely used this way.) Code: #include <tchar.h>
// Function guarantees not to modify the string, but alas, nobody made the parameter const.
void legacy(char *str);
void foo(const _TCHAR *txt)
{
legacy(txt); // Doesn't compile.
}
OK, once again, you solve this with a C-style cast: Code: #include <tchar.h>
// Function guarantees not to modify the string, but alas, nobody made the parameter const.
void legacy(char *str);
void foo(const _TCHAR *txt)
{
legacy((char*)txt);
}
Code: #define _UNICODE
#include <tchar.h>
// Function guarantees not to modify the string, but alas, nobody made the parameter const.
void legacy(char *str);
void foo(const _TCHAR *txt)
{
legacy((char*)txt);
}
Had you used a const_cast, it would now fail and you would be alerted to the fact that you have to account for these circumstances: Code: #include <tchar.h>
// Function guarantees not to modify the string, but alas, nobody made the parameter const.
void legacy(char *str);
void foo(const _TCHAR *txt)
{
legacy(const_cast<char*>(txt)); // Compiles only if _TCHAR is char.
}
2) Templates. When you don't know the actual types you get, limiting the stuff a cast may do is more important than ever. 3) Searchability. Imagine your program crashes with an access violation: a pointer is set to nirvana. Now there's typically four causes for this kind of bug. a. Uninitialized variables. b. Referencing pointers after they've been deleted. c. Overwriting the pointer due to a buffer overflow. d. Bogus casts from integral types. The first three are tricky to detect, but the fourth is rather easy to double-check: just search for all casts between integrals and pointers and make sure they all make sense. Except ... how do you find pointer casts? How do they differ from parenthesed expressions, from function declarations or function calls? In C, they don't: it's all a pair of parentheses. In C++, you know it's where the reinterpret_casts are. It's easy to search for. 4) Casts are bad. Every cast is a potential design problem. Some are unavoidable, some are just fine, but every single one must be considered carefully. Hopefully, writing the full operator makes you think harder about using the cast. Typing a pair of parentheses is just too easy. 5) Polymorphism. At the end of the day, the C-style cast simply cannot do what dynamic_cast does. Rule of thumb: just because the compiler allows it, doesn't mean it's a good thing. The compiler allows you to write a 10000 line main() littered with gotos jumping all over the place. Most compilers allow you to call main() explicitly, although such a thing is forbidden by the standard. Look at the entries of the Obfuscated C contest for a taste of all the stuff that the compiler allows that is a really bad idea.
__________________ All the buzzt! CornedBee"There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code." - Flon's Law |
| CornedBee is offline |
| Thread Tools | |
| Display Modes | |
|