c++undefined-behaviordynamic-castdowncaststatic-cast

When can static_cast be used safely for downcasting in C++?


I need to know under which conditions static_cast can be used in order to convert a parent class pointer to a child class pointer without causing an undefined behavior.

Usually dynamic_cast is recommended for safe downcasting, but what if the pointer that originally pointed to a parent class object never uses any member of the child class? Is it safe to use static_cast in this case?

If yes, then the following example code should not lead to any undefined behavior.

Example:

struct Parent {
    int i = 3;
    void print() { std::cout << i << std::endl; }
};
struct Child : Parent {
    double d = 5;
    void change() { i *= 2; }
};

int main() {
    Parent* pParent = new Parent;
    Child* pChild = static_cast<Child*>(pParent);
    pChild->print(); //should be ok
    //std::cout << pChild->d << std::endl; //undefined behavior
    //pChild->change(); //does this lead to an undefined behavior?
}

Bonus question: Is it safe to use a member function from the child class, if that function only uses members from the parent class? In the example above this would mean the use of

pChild->change();

Goal: My goal is to avoid dynamic_cast in order to safe performance. As long as I know how to avoid an undefined behavior for sure I am willing to take the risk of using static_cast instead. There are already existing threads about downcasting with static_cast, but none of them really answers under which conditions an undefined behavior can be avoided.


Solution

  • but what if the pointer that originally pointed to a parent class object never uses any member of the child class? Is it safe to use static_cast in this case?

    No, the behavior is still undefined.

    If yes, then the following example code should not lead to any undefined behavior.

    The example has undefined behavior because pParent points to an object of type Parent that is not a base class subobject of some Child object, which according to the standard causes causes static_cast<Child*>(pParent) to have undefined behavior.

    Bonus question: Is it safe to use a member function from the child class, if that function only uses members from the parent class?

    No, the cast itself, even if the result is not used at all, has undefined behavior.

    Goal: My goal is to avoid dynamic_cast in order to safe performance.

    You can use static_cast safely for downcasts in exactly the same circumstances in which dynamic_cast would not return a null pointer. In the other cases, the static_cast will have undefined behavior. That's precisely why static_cast is faster.

    It is impossible to obtain a pointer to a Child if the Parent object wasn't created as base class subobject while creating a Child object. The language does not permit this at all. To operate on a Child* in any way, you need to create a Child object first.

    Usually it is better to use an appropriate virtual function interface instead of dynamic_cast. This is both more performant and doesn't violate OOP principles like dynamic_cast does.