C++ Study Note(2): Cast the light to the darkness
cppThe old-school C casting is reckless without type checking, to make it worse,
the casting is easily overlooked by the maintainers. C++ introduces four cast
keywords to rescue: const_cast
, static_cast
, dynamic_cast
, and
reinterpret_cast
.
The keyword const
is a contract between the library developers and users.
Dropping the const decorator may incur unexpected behavior, for example:
class Foo
{
public:
Foo() : dd(0) {}
// int& bar() { cout << "non-const " << dd << endl; return dd; }
const int& bar() const { cout << "const " << dd << endl; return dd; }
private:
int dd;
};
... ...
Foo foo;
int & x = const_cast<int&>(foo.bar());
x = 3;
C++ impose the developers to use const_cast
to highlight the action,
otherwise, The warning is raised:
Warning, warning, the const decoration is dropped...
, the same rule applies to
the bool
type.
If you are quite confident the type downcasting, static_cast
is the right
option for you. The compiler would adjust the offset and return a derived class
pointer for you in the compile time, aka free overhead. If you could not
guarantee the heritage, use dynamic_cast, the runtime would try to down cast the
pointer/reference and return a valid pointer/reference if everything is OK,
otherwise, a null pointer is returned for pointer down-casting, or a bad_cast
exception is raised for the reference casting.
Update: Boost’s developers dislike the
inconsistences, a new cast template function, polymorph_cast
is introduced for
the downcasting and crosscasting:
template
inline Target polymorphic_cast(Source* x BOOST_EXPLICIT_DEFAULT_TARGET)
{
Target tmp = dynamic_cast(x);
if ( tmp == 0 ) throw std::bad_cast();
return tmp;
}
It helps the careless developers to test the validity of the returned pointer, throw an exception if necessary.
If you would like both the type safety from dynamic_cast
, and also the
performance of static_cast
, Boost has another neat cast function,
polymorphic_downcast
for you such a greedy jerk.
template
inline Target polymorphic_downcast(Source* x BOOST_EXPLICIT_DEFAULT_TARGET)
{
BOOST_ASSERT( dynamic_cast(x) == x ); // detect logic error
return static_cast(x);
}
This cast only works on downcast the pointer, you can tell from the name; it
does dynamic_cast
in the debug version and static_cast
in the release
version.
Last and the least, reinterpret_cast
, the compiler would just simply pretend
the object has a new type without any validation check, offset adjustment;
furthermore, it is NOT portable. Use it in caution and make sure you know
clearly what you are doing.