Reputation: 159
#include <iostream>
class Base {
};
class Derived : public Base {
};
int main() {
Base* bptr = new Derived();
Derived* dptr = static_cast<Derived*>(bptr);
std::cout << dptr << std::endl;
}
In the above code, I should be using dynamic_cast
but am using
static_cast
incorrectly. static_cast
should never be used while
downcasting, since compiler has no way to determine we are doing
cast correctly.
Why isn't this a compile error? I am using gcc 4.9.2. Do you guys think this is a bug in the compiler, or does C++ standards allow such code ?
Edit: Thanks for the responses. Actually, Base
class above is polymorphic,
i.e. it has virtual functions, but I left them out for this example. I should
have thrown in a virtual destructor in the Base to make it clear that it
was polymorphic – my bad.
Upvotes: 1
Views: 5268
Reputation: 16017
You are using static_cast
perfectly correctly. You are right, the compiler can in the general case not know whether the cast is correct, but static_cast
is exactly there for this scenario.
You cannot use dynamic_cast
here because that cast is for polymorphic classes (those which have a virtual member function). These classes carry run-time information; that information allows the code to choose the correct implementation of that function in the actual type of the object pointed to. This type information in the object can be used by the cast function to determine whether the type conversion is possible, and then indeed perform the conversion properly (which can be tricky with multiple and virtual inheritance).
Classes without virtual functions, like your example classes, do not carry this run time information, and dynamic_cast
cannot be used to cast to a more derived type. (It can still be used to cast to the same type or to a base class, i.e. it can be used for conversions which do actually not need a cast.)
Upvotes: 0
Reputation: 302748
In the above code, I should be using
dynamic_cast
but am usingstatic_cast
incorrectly.static_cast
should never be used while downcasting, since compiler has no way to determine we are doing cast correctly.
Ironically, the dynamic_cast
would actually be the ill-formed cast here, since your types are not polymorphic.
That said, static_cast
can certainly be used to downcast. You are correct that the compiler cannot do type-checking, but there are many situations in which you have a Base*
and know that it points to a Derived*
, so you can just manually do the cast. One very common case is CRTP:
template <class Derived>
class Base {
Derived& self() { return *static_cast<Derived*>(this); }
// ...
};
class Foo : Base<Foo> { ... };
Base<T>
is always a T
, so that downcast is safe.
The advantage of static_cast
over dynamic_cast
is that static_cast
is free but dynamic_cast
is expensive. The C++ mantra is don't pay for what you don't need.
Upvotes: 8
Reputation: 13220
static_cast < new_type > ( expression )
If
new_type
is a pointer or reference to some class D and the type ofexpression
is a pointer or reference to its non-virtual base B, static_cast performs a downcast. This downcast is ill-formed if B is ambiguous, inaccessible, or virtual base (or a base of a virtual base) of D. Such static_cast makes no runtime checks to ensure that the object's runtime type is actually D, and may only be used safely if this precondition is guaranteed by other means, such as when implementing static polymorphism. Safe downcast may be done with dynamic_cast.
Source (Explanation item 2)
Upvotes: 1