Amarnath Shanbhag
Amarnath Shanbhag

Reputation: 159

C++ static_cast vs dynamic_cast

#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

Answers (3)

Peter - Reinstate Monica
Peter - Reinstate Monica

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

Barry
Barry

Reputation: 302748

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.

Upvotes: 8

Alper
Alper

Reputation: 13220

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)

Upvotes: 1

Related Questions