1
#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.

2
  • 6
    You are allowed to static_cast from Base* to Derived*, but you are correct that it will not perform any type-checking. It is still useful though, if you know through some other way that that pointer does actually point to a Dervied object. If the Base* didn't actually point to a Derived* then any dereferencing of the Derived* resulting from a static_cast would invoke undefined behaviour. Commented Jan 12, 2017 at 17:22
  • In all reality, this is exactly what the static_castis for; after all, conversions towards base class pointers/references are done implicitly. Commented Jan 12, 2017 at 17:23

3 Answers 3

8

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.

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.

Sign up to request clarification or add additional context in comments.

Comments

1

static_cast < new_type > ( expression )

If new_type is a pointer or reference to some class D and the type of expression 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)

Comments

0

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.)

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.